Merge remote branch 'origin/sourceview'
authorJohn Darrington <john@darrington.wattle.id.au>
Sat, 20 Aug 2011 05:52:41 +0000 (07:52 +0200)
committerJohn Darrington <john@darrington.wattle.id.au>
Sat, 20 Aug 2011 05:52:41 +0000 (07:52 +0200)
169 files changed:
Makefile.am
NEWS
README.Git
Smake
configure.ac
doc/files.texi
doc/statistics.texi
doc/transformation.texi
doc/variables.texi
lib/automake.mk
lib/gtk-contrib/automake.mk
lib/gtk-contrib/gtkxpaned.c
lib/tukey/README [new file with mode: 0644]
lib/tukey/automake.mk [new file with mode: 0644]
lib/tukey/ptukey.c [new file with mode: 0644]
lib/tukey/qtukey.c [new file with mode: 0644]
lib/tukey/tukey.h [new file with mode: 0644]
perl-module/PSPP.xs
perl-module/lib/PSPP.pm.in
perl-module/t/Pspp.t
po/automake.mk
po/ca.po
po/es.po
po/lt.po
src/data/automake.mk
src/data/file-name.c
src/data/format.c
src/data/gnumeric-reader.c
src/data/gnumeric-reader.h
src/data/ods-reader.c [new file with mode: 0644]
src/data/ods-reader.h [new file with mode: 0644]
src/data/spreadsheet-reader.c [new file with mode: 0644]
src/data/spreadsheet-reader.h [new file with mode: 0644]
src/data/variable.c
src/language/command.def
src/language/data-io/get-data.c
src/language/expressions/evaluate.c
src/language/expressions/optimize.c
src/language/expressions/private.h
src/language/stats/automake.mk
src/language/stats/autorecode.c
src/language/stats/descriptives.c
src/language/stats/factor.c
src/language/stats/flip.c
src/language/stats/glm.c
src/language/stats/ks-one-sample.c [new file with mode: 0644]
src/language/stats/ks-one-sample.h [new file with mode: 0644]
src/language/stats/mcnemar.c [new file with mode: 0644]
src/language/stats/mcnemar.h [new file with mode: 0644]
src/language/stats/npar.c
src/language/stats/oneway.c
src/language/stats/quick-cluster.c
src/language/stats/runs.c
src/language/stats/t-test-indep.c [new file with mode: 0644]
src/language/stats/t-test-one-sample.c [new file with mode: 0644]
src/language/stats/t-test-paired.c [new file with mode: 0644]
src/language/stats/t-test-parser.c [new file with mode: 0644]
src/language/stats/t-test.h [new file with mode: 0644]
src/language/stats/t-test.q [deleted file]
src/libpspp/automake.mk
src/libpspp/cast.h
src/libpspp/ext-array.c
src/libpspp/hash.c [deleted file]
src/libpspp/hash.h [deleted file]
src/libpspp/inflate.c [new file with mode: 0644]
src/libpspp/inflate.h [new file with mode: 0644]
src/libpspp/temp-file.c
src/libpspp/zip-private.h [new file with mode: 0644]
src/libpspp/zip-reader.c [new file with mode: 0644]
src/libpspp/zip-reader.h [new file with mode: 0644]
src/libpspp/zip-writer.c
src/math/automake.mk
src/math/categoricals.c
src/math/categoricals.h
src/math/covariance.c
src/math/covariance.h
src/math/group-proc.h [deleted file]
src/math/group.c [deleted file]
src/math/group.h [deleted file]
src/math/interaction.c
src/math/interaction.h
src/math/levene.c
src/math/levene.h
src/output/automake.mk
src/output/driver.c
src/output/render.c
src/ui/gui/aggregate-dialog.c
src/ui/gui/aggregate.ui
src/ui/gui/automake.mk
src/ui/gui/autorecode-dialog.c [new file with mode: 0644]
src/ui/gui/autorecode-dialog.h [new file with mode: 0644]
src/ui/gui/autorecode.ui [new file with mode: 0644]
src/ui/gui/binomial.ui
src/ui/gui/chi-square.ui
src/ui/gui/correlation.ui
src/ui/gui/count-dialog.c [new file with mode: 0644]
src/ui/gui/count-dialog.h [new file with mode: 0644]
src/ui/gui/count.ui [new file with mode: 0644]
src/ui/gui/crosstabs.ui
src/ui/gui/customentry.c
src/ui/gui/data-editor.ui
src/ui/gui/descriptives.ui
src/ui/gui/factor-dialog.c
src/ui/gui/factor.ui
src/ui/gui/frequencies.ui
src/ui/gui/help-menu.c
src/ui/gui/k-means-dialog.c [new file with mode: 0644]
src/ui/gui/k-means-dialog.h [new file with mode: 0644]
src/ui/gui/k-means.ui [new file with mode: 0644]
src/ui/gui/k-related.ui
src/ui/gui/ks-one-sample-dialog.c [new file with mode: 0644]
src/ui/gui/ks-one-sample-dialog.h [new file with mode: 0644]
src/ui/gui/ks-one-sample.ui [new file with mode: 0644]
src/ui/gui/main.c
src/ui/gui/npar-two-sample-related.c [new file with mode: 0644]
src/ui/gui/npar-two-sample-related.h [new file with mode: 0644]
src/ui/gui/oneway.ui
src/ui/gui/paired-dialog.c [new file with mode: 0644]
src/ui/gui/paired-dialog.h [new file with mode: 0644]
src/ui/gui/paired-samples.ui [new file with mode: 0644]
src/ui/gui/psppire-data-window.c
src/ui/gui/psppire-dialog.c
src/ui/gui/psppire-keypad.c
src/ui/gui/psppire-keypad.h
src/ui/gui/psppire-output-window.c
src/ui/gui/psppire-scanf.c [new file with mode: 0644]
src/ui/gui/psppire-scanf.h [new file with mode: 0644]
src/ui/gui/psppire-selector.c
src/ui/gui/psppire-selector.h
src/ui/gui/psppire-syntax-window.c
src/ui/gui/psppire-val-chooser.c [new file with mode: 0644]
src/ui/gui/psppire-val-chooser.h [new file with mode: 0644]
src/ui/gui/psppire-window.c
src/ui/gui/recode-dialog.c
src/ui/gui/recode.ui
src/ui/gui/regression.ui
src/ui/gui/reliability.ui
src/ui/gui/roc.ui
src/ui/gui/runs-dialog.c [new file with mode: 0644]
src/ui/gui/runs-dialog.h [new file with mode: 0644]
src/ui/gui/runs.ui [new file with mode: 0644]
src/ui/gui/select-cases-dialog.c
src/ui/gui/t-test-independent-samples-dialog.c
src/ui/gui/t-test-one-sample.c
src/ui/gui/t-test-options.c
src/ui/gui/t-test-options.h
src/ui/gui/t-test-paired-samples.c
src/ui/gui/t-test.ui
src/ui/gui/text-data-import-dialog.c
src/ui/gui/var-sheet-dialogs.ui
src/ui/gui/widget-io.c
src/ui/gui/widget-io.h
src/ui/gui/widgets.c
src/ui/terminal/terminal-reader.c
tests/atlocal.in
tests/automake.mk
tests/language/data-io/get-data-gnm.at [deleted file]
tests/language/data-io/get-data-spreadsheet.at [new file with mode: 0644]
tests/language/data-io/test.ods [new file with mode: 0644]
tests/language/stats/autorecode.at
tests/language/stats/glm.at [new file with mode: 0644]
tests/language/stats/npar.at
tests/language/stats/oneway.at
tests/language/stats/quick-cluster.at
tests/language/stats/t-test.at
tests/libpspp/range-set-test.c
tests/libpspp/zip-test.c [new file with mode: 0644]
tests/libpspp/zip.at [new file with mode: 0644]
tests/perl-module.at

index bed99f40c9a44a023f0423083e2c3109f60123e2..28e9ffc6b250078acdc65da2ddebfc1bfee5dd52 100644 (file)
@@ -49,7 +49,7 @@ LDADD = gl/libgl.la
 
 generate-changelog:
        if test -d $(top_srcdir)/.git; then                     \
-         $(top_srcdir)/gitlog-to-changelog --since=2008-07-27  \
+         $(top_srcdir)/build-aux/gitlog-to-changelog --since=2008-07-27        \
            > $(distdir)/cl-t;                                  \
          rm -f $(distdir)/ChangeLog;                           \
          mv $(distdir)/cl-t $(distdir)/ChangeLog;              \
diff --git a/NEWS b/NEWS
index 57d2d7b59cae7d1f01c580e8d315e49090cca9f5..0faa8ca2c5a08a3d3f46717698cbe04522f85c75 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -44,8 +44,11 @@ Changes from 0.6.2 to 0.7.8:
    - MISSING VALUES can now assign missing values to long string
      variables.
 
-   - NPAR TESTS has new KRUSKAL-WALLIS, SIGN, WILCOXON, and RUNS
-     subcommands.
+   - ONEWAY: the POSTHOC subcommand is now implemented.
+
+   - The following new subcommands to NPAR TESTS have been implemented:
+     COCHRAN, FRIEDMAN, KENDALL, KRUSKAL-WALLIS, MANN-WHITNEY, MCNEMAR,
+     SIGN, WILCOXON, and RUNS
 
    - SET and SHOW no longer have ENDCMD, NULLINE, PROMPT, CPROMPT, and
      DPROMPT subcommands.  The defaults are now fixed values.
@@ -100,6 +103,10 @@ Changes from 0.6.2 to 0.7.8:
      characters, including double-width characters and combining
      accents.
 
+   - Output to OpenDocument format is now supported.
+
+   - The HTML output is much improved.
+
  * The "pspp" program has a new option --batch (or -b) that selects
    "batch" syntax mode.  In previous versions of PSPP this syntax mode
    was the default.  Now a new "auto" syntax mode is the default.  In
index b8cc4207cec19dc69f177fb44b197207d2c2ec2e..b437237ca23560592d487faba9ce4c667d4e2f59 100644 (file)
@@ -34,14 +34,18 @@ This version of PSPP should work with the Gnulib commit shown below.
 Gnulib does not maintain a stable API or ABI, so it is possible that
 PSPP will not work with older or newer versions of Gnulib.
 
-  commit a38e4bbf37c4a77ea65f548dfcf590cf23e73d7e
-  Author: Bruno Haible <bruno@clisp.org>
-  Date:   Sun Feb 13 18:04:55 2011 +0100
-
-      mbsinit: Don't crash for a NULL argument.
-
-      * lib/mbsinit.c (mbsinit): When the argument is NULL, return 1.
-      * tests/test-mbsinit.c (mbsinit): Check this behaviour.
+  commit fb6aa6ad7dd950729f4e3349d89d4ad82761af61
+  Author: Ben Pfaff <blp@cs.stanford.edu>
+  Date:   Mon Aug 15 22:33:25 2011 -0700
+
+      relocatable-prog: fix link error
+
+      * modules/relocatable-prog (configure.ac) [RELOCATABLE]: Also
+      invoke AC_LIBOBJ([relocatable]).  This invocation was previously
+      in the gl_RELOCATABLE_LIBRARY macro.  That invocation was moved
+      into modules/relocatable-lib without noticing that
+      modules/relocatable-prog also invokes gl_RELOCATABLE_LIBRARY and
+      also needs to build relocatable.c.
 
 To clone Gnulib into a directory named "gnulib" using Git, and then
 check out this particular commit, run these commands:
diff --git a/Smake b/Smake
index 4cbe44ece9a3060f9549b2fe7e345591b5f48623..acd93102be0632c517e739bfa116cbe2c8e5a5eb 100644 (file)
--- a/Smake
+++ b/Smake
@@ -43,6 +43,7 @@ GNULIB_MODULES = \
        inttostr \
        localcharset \
         mbchar \
+        mbiter \
        memcasecmp \
        memchr \
        mempcpy \
@@ -66,13 +67,10 @@ GNULIB_MODULES = \
        stdbool \
        stdint \
        stpcpy \
-       strcase \
        strerror \
        strftime \
        strtod \
        strtok_r \
-       strtol \
-       strtoul \
        sys_stat \
        tempname \
        trunc \
index 766d5a43859d43a26aa9c7771dcf959379861a98..1456b66138eaf537a40cedd6a39325b4f143a088 100644 (file)
@@ -199,24 +199,30 @@ AC_DEFINE(
   [crc32], [gl_crc32],
   [Avoid making zlib call gnulib's crc32() instead of its own.])
 
-dnl Gnumeric support requires libxml2 and zlib.
+dnl Gnumeric and OpenDocument (read) support requires libxml2 and zlib.
 if test $HAVE_LIBXML2 = yes && test $HAVE_ZLIB = yes; then
   GNM_SUPPORT=yes
+  ODF_READ_SUPPORT=yes
   AC_DEFINE(
     [GNM_SUPPORT], [1],
     [Define to 1 if building in support for reading Gnumeric files.])
+  AC_DEFINE(
+    [ODF_READ_SUPPORT], [1],
+    [Define to 1 if building in support for reading OpenDocument files.])
 else
   GNM_SUPPORT=no
+  ODF_READ_SUPPORT=no
 fi
 AC_SUBST([GNM_SUPPORT])
+AC_SUBST([ODF_READ_SUPPORT])
 
-dnl ODT support requires libxml2.
+dnl ODF support requires libxml2 (zlib is optional).
 if test $HAVE_LIBXML2 = yes; then
   AC_DEFINE(
-    [ODT_SUPPORT], [1],
-    [Define to 1 if building in support for writing ODT files.])
+    [ODF_WRITE_SUPPORT], [1],
+    [Define to 1 if building in support for writing OpenDocument files.])
 fi
-AM_CONDITIONAL([ODT_SUPPORT], [test $HAVE_LIBXML2 = yes])
+AM_CONDITIONAL([ODF_WRITE_SUPPORT], [test $HAVE_LIBXML2 = yes])
 
 AC_ARG_WITH(
   gui_tools,
index 89d043f8769f67c6c898dcf9a7729d0fbcd3356d..cdce0a3c4689875560ef57dad998253c5f51b5e2 100644 (file)
@@ -182,7 +182,7 @@ Use of @cmd{GET} to read a portable file is a PSPP extension.
 
 @display
 GET DATA
-        /TYPE=@{GNM,PSQL,TXT@}
+        /TYPE=@{GNM,ODS,PSQL,TXT@}
         @dots{}additional subcommands depending on TYPE@dots{}
 @end display
 
@@ -199,6 +199,9 @@ PSPP currently supports the following file types:
 @item GNM
 Spreadsheet files created by Gnumeric (@url{http://gnumeric.org}).
 
+@item ODS
+Spreadsheet files in OpenDocument format.
+
 @item PSQL
 Relations from PostgreSQL databases (@url{http://postgresql.org}).
 
@@ -210,16 +213,16 @@ Each supported file type has additional subcommands, explained in
 separate sections below.
 
 @menu
-* GET DATA /TYPE=GNM::
-* GET DATA /TYPE=PSQL::
-* GET DATA /TYPE=TXT::
+* GET DATA /TYPE=GNM/ODS::     Spreadsheets
+* GET DATA /TYPE=PSQL::        Databases
+* GET DATA /TYPE=TXT::         Delimited Text Files
 @end menu
 
-@node GET DATA /TYPE=GNM
-@subsection Gnumeric Spreadsheet Files
+@node GET DATA /TYPE=GNM/ODS
+@subsection Spreadsheet Files
 
 @display
-GET DATA /TYPE=GNM
+GET DATA /TYPE=@{GNM, ODS@}
         /FILE=@{'file-name'@}
         /SHEET=@{NAME 'sheet-name', INDEX n@}
         /CELLRANGE=@{RANGE 'range', FULL@}
@@ -228,11 +231,19 @@ GET DATA /TYPE=GNM
 @end display
 
 @cindex Gnumeric
+@cindex OpenDocument
 @cindex spreadsheet files
-To use GET DATA to read a spreadsheet file created by Gnumeric
-(@url{http://gnumeric.org}), specify TYPE=GNM to indicate the file's
-format and use FILE to indicate the Gnumeric file to be read.  All
-other subcommands are optional.
+
+Gnumeric spreadsheets (@url{http://gnumeric.org}), and spreadsheets
+in OpenDocument format
+(@url{http://libreplanet.org/wiki/Group:OpenDocument/Software})
+can be read using the GET DATA command.
+Use the TYPE subcommand to indicate the file's format.  
+/TYPE=GNM indicates Gnumeric files,
+/TYPE=ODS indicates OpenDocument.
+The FILE subcommand is mandatory.
+Use it to specify the name file to be read. 
+All other subcommands are optional.
 
 The format of each variable is determined by the format of the spreadsheet 
 cell containing the first datum for the variable.
@@ -240,10 +251,6 @@ If this cell is of string (text) format, then the width of the variable is
 determined from the length of the string it contains, unless the 
 ASSUMEDVARWIDTH subcommand is given.
 
-
-The FILE subcommand is mandatory. Specify the name of the file
-to be read.
-
 The SHEET subcommand specifies the sheet within the spreadsheet file to read.
 There are two forms of the SHEET subcommand.
 In the first form,
@@ -266,8 +273,8 @@ If no CELLRANGE subcommand is given, then the entire sheet is read.
 
 If @samp{/READNAMES=ON} is specified, then the contents of cells of
 the first row are used as the names of the variables in which to store
-the data from subsequent rows. 
-If the READNAMES command is omitted, or if @samp{/READNAMES=OFF} is
+the data from subsequent rows.  This is the default.
+If @samp{/READNAMES=OFF} is
 used, then the variables  receive automatically assigned names.
 
 The ASSUMEDVARWIDTH subcommand specifies the maximum width of string
index e5e299a47f8a66ae63688581de53a4b57e18d35b..b1121b498c24af28ddda49d8163d00e45673c355 100644 (file)
@@ -14,6 +14,7 @@ far.
 * NPAR TESTS::                  Nonparametric tests.
 * T-TEST::                      Test hypotheses about means.
 * ONEWAY::                      One way analysis of variance.
+* QUICK CLUSTER::               K-Means clustering.
 * RANK::                        Compute rank scores.
 * REGRESSION::                  Linear regression.
 * RELIABILITY::                 Reliability analysis.
@@ -555,7 +556,7 @@ FACTOR  VARIABLES=var_list
 
         [ /ROTATION=@{VARIMAX, EQUAMAX, QUARTIMAX, NOROTATE@}]
 
-        [ /PRINT=[INITIAL] [EXTRACTION] [ROTATION] [UNIVARIATE] [CORRELATION] [COVARIANCE] [DET] [SIG] [ALL] [DEFAULT] ]
+        [ /PRINT=[INITIAL] [EXTRACTION] [ROTATION] [UNIVARIATE] [CORRELATION] [COVARIANCE] [DET] [KMO] [SIG] [ALL] [DEFAULT] ]
 
         [ /PLOT=[EIGEN] ]
 
@@ -600,6 +601,8 @@ The /PRINT subcommand may be used to select which features of the analysis are r
       The covariance matrix is printed.
 @item DET
       The determinant of the correlation or covariance matrix is printed.
+@item KMO
+      The Kaiser-Meyer-Olkin measure of sampling adequacy and the Bartlett test of sphericity is printed.
 @item SIG
       The significance of the elements of correlation matrix is printed.
 @item ALL
@@ -684,8 +687,10 @@ is used.
 * COCHRAN::                 Cochran Q Test
 * FRIEDMAN::                Friedman Test
 * KENDALL::                 Kendall's W Test
+* KOLMOGOROV-SMIRNOV::      Kolmogorov Smirnov Test
 * KRUSKAL-WALLIS::          Kruskal-Wallis Test
 * MANN-WHITNEY::            Mann Whitney U Test
+* MCNEMAR::                 McNemar Test
 * RUNS::                    Runs Test
 * SIGN::                    The Sign Test
 * WILCOXON::                Wilcoxon Signed Ranks Test
@@ -814,6 +819,45 @@ It has the range [0,1] --- a value of zero indicates no agreement between the sa
 unity indicates complete agreement.
 
 
+@node KOLMOGOROV-SMIRNOV
+@subsection Kolmogorov-Smirnov Test
+@vindex KOLMOGOROV-SMIRNOV
+@vindex K-S
+@cindex Kolmogorov-Smirnov test
+
+@display
+     [ /KOLMOGOROV-SMIRNOV (@{NORMAL [@var{mu}, @var{sigma}], UNIFORM [@var{min}, @var{max}], POISSON [@var{lambda}], EXPONENTIAL [@var{scale}] @}) = varlist ]
+@end display
+
+The one sample Kolmogorov-Smirnov subcommand is used to test whether or not a dataset is
+drawn from a particular distribution.  Four distributions are supported, @i{viz:}
+Normal, Uniform, Poisson and Exponential.
+
+Ideally you should provide the parameters of the distribution against which you wish to test
+the data. For example, with the normal distribution  the mean (@var{mu})and standard deviation (@var{sigma})
+should be given; with the uniform distribution, the minimum (@var{min})and maximum (@var{max}) value should
+be provided.
+However, if the parameters are omitted they will be imputed from the data. Imputing the
+parameters reduces the power of the test so should be avoided if possible.
+
+In the following example, two variables @var{score} and @var{age} are tested to see if
+they follow a normal distribution with a mean of 3.5 and a standard deviation of 2.0.
+@example
+  NPAR TESTS
+        /KOLMOGOROV-SMIRNOV (normal 3.5 2.0) = @var{score} @var{age}.
+@end example
+If the variables need to be tested against different distributions, then a seperate
+subcommand must be used.  For example the following syntax tests @var{score} against
+a normal distribution with mean of 3.5 and standard deviation of 2.0 whilst @var{age}
+is tested against a normal distribution of mean 40 and standard deviation 1.5.
+@example
+  NPAR TESTS
+        /KOLMOGOROV-SMIRNOV (normal 3.5 2.0) = @var{score}
+        /KOLMOGOROV-SMIRNOV (normal 40 1.5) =  @var{age}.
+@end example
+
+The abbreviated subcommand  K-S may be used in place of KOLMOGOROV-SMIRNOV.
+
 @node KRUSKAL-WALLIS
 @subsection Kruskal-Wallis Test
 @vindex KRUSKAL-WALLIS
@@ -859,6 +903,33 @@ Cases for which the @var{var} value is neither @var{group1} or @var{group2} will
 The value of the Mann-Whitney U statistic, the Wilcoxon W, and the significance will be printed.
 The abbreviated subcommand  M-W may be used in place of MANN-WHITNEY.
 
+@node MCNEMAR
+@subsection McNemar Test
+@vindex MCNEMAR
+@cindex McNemar test
+
+@display
+     [ /MCNEMAR varlist [ WITH varlist [ (PAIRED) ]]]
+@end display
+
+Use McNemar's test to analyse the significance of the difference between
+pairs of correlated proportions.
+
+If the @code{WITH} keyword is omitted, then tests for all
+combinations of the listed variables are performed.
+If the @code{WITH} keyword is given, and the @code{(PAIRED)} keyword
+is also given, then the number of variables preceding @code{WITH}
+must be the same as the number following it.
+In this case, tests for each respective pair of variables are
+performed.
+If the @code{WITH} keyword is given, but the
+@code{(PAIRED)} keyword is omitted, then tests for each combination
+of variable preceding @code{WITH} against variable following
+@code{WITH} are performed.
+
+The data in each variable must be dichotomous.  If there are more
+than two distinct variables an error will occur and the test will
+not be run.
 
 @node RUNS
 @subsection Runs Test
@@ -866,7 +937,7 @@ The abbreviated subcommand  M-W may be used in place of MANN-WHITNEY.
 @cindex runs test
 
 @display 
-     [ /RUNS (@{MEAN, MEDIAN, MODE, value@}) varlist ]
+     [ /RUNS (@{MEAN, MEDIAN, MODE, value@})  = varlist ]
 @end display
 
 The /RUNS subcommand tests whether a data sequence is randomly ordered.
@@ -1073,7 +1144,7 @@ ONEWAY
         /MISSING=@{ANALYSIS,LISTWISE@} @{EXCLUDE,INCLUDE@}
         /CONTRAST= value1 [, value2] ... [,valueN]
         /STATISTICS=@{DESCRIPTIVES,HOMOGENEITY@}
-
+        /POSTHOC=@{BONFERRONI, GH, LSD, SCHEFFE, SIDAK, TUKEY, ALPHA ([value])@}
 @end display
 
 The @cmd{ONEWAY} procedure performs a one-way analysis of variance of
@@ -1117,11 +1188,76 @@ A setting of EXCLUDE means that variables whose values are
 user-missing are to be excluded from the analysis. A setting of
 INCLUDE means they are to be included.  The default is EXCLUDE.
 
+Using the @code{POSTHOC} subcommand you can perform multiple
+pairwise comparisons on the data. The following comparison methods
+are available:
+@itemize
+@item LSD
+Least Significant Difference.
+@item TUKEY
+Tukey Honestly Significant Difference.
+@item BONFERRONI
+Bonferroni test.
+@item SCHEFFE
+Scheff@'e's test.
+@item SIDAK
+Sidak test.
+@item GH
+The Games-Howell test.
+@end itemize
+
+@noindent
+The optional syntax @code{ALPHA(@var{value})} is used to indicate
+that @var{value} should be used as the
+confidence level for which the posthoc tests will be performed.
+The default is 0.05.
+
+@node QUICK CLUSTER
+@comment  node-name,  next,  previous,  up
+@section QUICK CLUSTER
+@vindex QUICK CLUSTER
+
+@cindex K-means clustering
+@cindex clustering
+
+@display
+QUICK CLUSTER var_list
+      [/CRITERIA=CLUSTERS(@var{k}) [MXITER(@var{max_iter})]]
+      [/MISSING=@{EXCLUDE,INCLUDE@} @{LISTWISE, PAIRWISE@}]
+@end display
+
+The @cmd{QUICK CLUSTER} command performs k-means clustering on the
+dataset.  This is useful when you wish to allocate cases into clusters
+of similar values and you already know the number of clusters.
+
+The minimum specification is @samp{QUICK CLUSTER} followed by the names
+of the variables which contain the cluster data.  Normally you will also
+want to specify @samp{/CRITERIA=CLUSTERS(@var{k})} where @var{k} is the
+number of clusters.  If this is not given, then @var{k} defaults to 2.
+
+The command uses an iterative algorithm to determine the clusters for
+each case.  It will continue iterating until convergence, or until @var{max_iter}
+iterations have been done.  The default value of @var{max_iter} is 2.
+
+The @cmd{MISSING} subcommand determines the handling of missing variables.  
+If INCLUDE is set, then user-missing values are considered at their face
+value and not as missing values.
+If EXCLUDE is set, which is the default, user-missing
+values are excluded as well as system-missing values. 
+
+If LISTWISE is set, then the entire case is excluded from the analysis
+whenever any of the clustering variables contains a missing value.   
+If PAIRWISE is set, then a case is considered missing only if all the
+clustering variables contain missing values.  Otherwise it is clustered
+on the basis of the non-missing values.
+The default is LISTWISE.
+
 
 @node RANK
 @comment  node-name,  next,  previous,  up
 @section RANK
 
+
 @vindex RANK
 @display
 RANK
index f1d1cbf2617b649c5393b10428325329c696447d..883584b91f794bb4ccd8091b5cbaf6ff17fdc8af 100644 (file)
@@ -223,6 +223,7 @@ AUTORECODE VARIABLES=src_vars INTO dest_vars
         [ /DESCENDING ]
         [ /PRINT ]
         [ /GROUP ]
+        [ /BLANK = @{VALID, MISSING@} ]
 @end display
 
 The @cmd{AUTORECODE} procedure considers the @var{n} values that a variable
@@ -247,6 +248,11 @@ The GROUP subcommand is relevant only if more than one variable is to be
 recoded.   It causes a single mapping between source and target values to
 be used, instead of one map per variable.
 
+If /BLANK=MISSING is given, then string variables which contain only 
+whitespace are recoded as SYSMIS.  If /BLANK=VALID is given then they
+will be allocated a value like any other.  /BLANK is not relevant
+to numeric values. /BLANK=VALID is the default.
+
 @cmd{AUTORECODE} is a procedure.  It causes the data to be read.
 
 @node COMPUTE
index 650c7d2c6143d05acb34af577a1458d82b4c227d..cc73470fd559477867416d64d7b774e2ff8f3fa6 100644 (file)
@@ -276,25 +276,6 @@ not.
 @cmd{MODIFY VARS} may not be specified following @cmd{TEMPORARY}
 (@pxref{TEMPORARY}).
 
-@node NUMERIC
-@section NUMERIC
-@vindex NUMERIC
-
-@display
-NUMERIC /var_list [(fmt_spec)].
-@end display
-
-@cmd{NUMERIC} explicitly declares new numeric variables, optionally
-setting their output formats.
-
-Specify a slash (@samp{/}), followed by the names of the new numeric
-variables.  If you wish to set their output formats, follow their names
-by an output format specification in parentheses (@pxref{Input and Output
-Formats}); otherwise, the default is F8.2.
-
-Variables created with @cmd{NUMERIC} are initialized to the
-system-missing value.
-
 @node MRSETS
 @section MRSETS
 @vindex MRSETS
@@ -402,6 +383,25 @@ Multiple response sets are saved to and read from system files by,
 e.g., the @cmd{SAVE} and @cmd{GET} command.  Otherwise, multiple
 response sets are currently used only by third party software.
 
+@node NUMERIC
+@section NUMERIC
+@vindex NUMERIC
+
+@display
+NUMERIC /var_list [(fmt_spec)].
+@end display
+
+@cmd{NUMERIC} explicitly declares new numeric variables, optionally
+setting their output formats.
+
+Specify a slash (@samp{/}), followed by the names of the new numeric
+variables.  If you wish to set their output formats, follow their names
+by an output format specification in parentheses (@pxref{Input and Output
+Formats}); otherwise, the default is F8.2.
+
+Variables created with @cmd{NUMERIC} are initialized to the
+system-missing value.
+
 @node PRINT FORMATS
 @section PRINT FORMATS
 @vindex PRINT FORMATS
index 9bde4afcf26d77b9950e960cdfd29063b7cbbbeb..3fb94bfe6fff0dc9fda19095aadbeeb0fe0cb878 100644 (file)
@@ -1,6 +1,7 @@
 ## Process this file with automake to produce Makefile.in  -*- makefile -*-
 
 include $(top_srcdir)/lib/linreg/automake.mk
+include $(top_srcdir)/lib/tukey/automake.mk
 
 if HAVE_GUI
 include $(top_srcdir)/lib/gtk-contrib/automake.mk
index b39bdb38786fe7d4f06ba4131a61427efb8fed0d..e694d714cdb345b445dfb49978e26b1f4bccdf93 100644 (file)
@@ -2,6 +2,7 @@
 
 noinst_LIBRARIES += lib/gtk-contrib/libgtksheet.a
 
+lib_gtk_contrib_libgtksheet_a_CPPFLAGS = $(AM_CPPFLAGS) -Isrc/ui/gui/include
 lib_gtk_contrib_libgtksheet_a_CFLAGS = $(GTK_CFLAGS) -Wall -DGDK_MULTIHEAD_SAFE=1
 
 lib_gtk_contrib_libgtksheet_a_SOURCES = \
index e350295a3e3f40bbcf687ca3f3bcf7438bec217c..19621c39ff56a377ee5313fee9ad82ebcbb6bfbc 100644 (file)
 
 #include <config.h>
 #include "gtkxpaned.h"
+
+#include <gtk/gtk.h>
 #include <ui/gui/psppire-marshal.h>
-#include <gtk/gtkbindings.h>
-#include <gtk/gtksignal.h>
 #include <gdk/gdkkeysyms.h>
-#include <gtk/gtkwindow.h>
-#include <gtk/gtkmain.h>
+
 
 enum WidgetProperties
 {
@@ -660,7 +659,7 @@ static void gtk_xpaned_size_request (GtkWidget* widget,
        requisition->width = 0;
        requisition->height = 0;
 
-       if (xpaned->top_left_child && GTK_WIDGET_VISIBLE (xpaned->top_left_child))
+       if (xpaned->top_left_child && gtk_widget_get_visible (xpaned->top_left_child))
        {
                gtk_widget_size_request (xpaned->top_left_child, &child_requisition);
 
@@ -668,7 +667,7 @@ static void gtk_xpaned_size_request (GtkWidget* widget,
                requisition->height = child_requisition.height;
        }
 
-       if (xpaned->top_right_child && GTK_WIDGET_VISIBLE (xpaned->top_right_child))
+       if (xpaned->top_right_child && gtk_widget_get_visible (xpaned->top_right_child))
        {
                gtk_widget_size_request (xpaned->top_right_child, &child_requisition);
 
@@ -676,7 +675,7 @@ static void gtk_xpaned_size_request (GtkWidget* widget,
                requisition->height = MAX (requisition->height, child_requisition.height);
        }
 
-       if (xpaned->bottom_left_child && GTK_WIDGET_VISIBLE (xpaned->bottom_left_child))
+       if (xpaned->bottom_left_child && gtk_widget_get_visible (xpaned->bottom_left_child))
        {
                gtk_widget_size_request (xpaned->bottom_left_child, &child_requisition);
 
@@ -684,7 +683,7 @@ static void gtk_xpaned_size_request (GtkWidget* widget,
                requisition->height += child_requisition.height;
        }
 
-       if (xpaned->bottom_right_child && GTK_WIDGET_VISIBLE (xpaned->bottom_right_child))
+       if (xpaned->bottom_right_child && gtk_widget_get_visible (xpaned->bottom_right_child))
        {
                gtk_widget_size_request (xpaned->bottom_right_child, &child_requisition);
 
@@ -697,10 +696,10 @@ static void gtk_xpaned_size_request (GtkWidget* widget,
        requisition->height += GTK_CONTAINER (xpaned)->border_width * 2;
 
        /* also add the handle "thickness" to GtkXPaneds width- and height-requisitions */
-       if (xpaned->top_left_child && GTK_WIDGET_VISIBLE (xpaned->top_left_child) &&
-               xpaned->top_right_child && GTK_WIDGET_VISIBLE (xpaned->top_right_child) &&
-               xpaned->bottom_left_child && GTK_WIDGET_VISIBLE (xpaned->bottom_left_child) &&
-               xpaned->bottom_right_child && GTK_WIDGET_VISIBLE (xpaned->bottom_right_child))
+       if (xpaned->top_left_child && gtk_widget_get_visible (xpaned->top_left_child) &&
+               xpaned->top_right_child && gtk_widget_get_visible (xpaned->top_right_child) &&
+               xpaned->bottom_left_child && gtk_widget_get_visible (xpaned->bottom_left_child) &&
+               xpaned->bottom_right_child && gtk_widget_get_visible (xpaned->bottom_right_child))
        {
                gint handle_size;
 
@@ -739,10 +738,10 @@ static void gtk_xpaned_size_allocate (GtkWidget* widget,
 
        widget->allocation = *allocation;
 
-       if (xpaned->top_left_child && GTK_WIDGET_VISIBLE (xpaned->top_left_child) &&
-               xpaned->top_right_child && GTK_WIDGET_VISIBLE (xpaned->top_right_child) &&
-               xpaned->bottom_left_child && GTK_WIDGET_VISIBLE (xpaned->bottom_left_child) &&
-               xpaned->bottom_right_child && GTK_WIDGET_VISIBLE (xpaned->bottom_right_child))
+       if (xpaned->top_left_child && gtk_widget_get_visible (xpaned->top_left_child) &&
+               xpaned->top_right_child && gtk_widget_get_visible (xpaned->top_right_child) &&
+               xpaned->bottom_left_child && gtk_widget_get_visible (xpaned->bottom_left_child) &&
+               xpaned->bottom_right_child && gtk_widget_get_visible (xpaned->bottom_right_child))
     {
                /* what sizes do the children want to be at least at */
                gtk_widget_get_child_requisition (xpaned->top_left_child,
@@ -815,9 +814,9 @@ static void gtk_xpaned_size_allocate (GtkWidget* widget,
                bottom_right_child_allocation.width = xpaned->handle_pos_east.width;
                bottom_right_child_allocation.height = xpaned->handle_pos_south.height;
 
-               if (GTK_WIDGET_REALIZED (widget))
+               if (gtk_widget_get_realized (widget))
                {
-                       if (GTK_WIDGET_MAPPED (widget))
+                       if (gtk_widget_get_mapped (widget))
                        {
                                gdk_window_show (xpaned->handle_east);
                                gdk_window_show (xpaned->handle_west);
@@ -860,7 +859,7 @@ static void gtk_xpaned_size_allocate (GtkWidget* widget,
                /* Now allocate the childen, making sure, when resizing not to
                * overlap the windows
                */
-               if (GTK_WIDGET_MAPPED (widget))
+               if (gtk_widget_get_mapped (widget))
                {
                        gtk_widget_size_allocate (xpaned->top_right_child, &top_right_child_allocation);
                        gtk_widget_size_allocate (xpaned->top_left_child, &top_left_child_allocation);
@@ -1216,10 +1215,10 @@ static void gtk_xpaned_realize (GtkWidget* widget)
 
        widget->style = gtk_style_attach (widget->style, widget->window);
 
-       if (xpaned->top_left_child && GTK_WIDGET_VISIBLE (xpaned->top_left_child) &&
-               xpaned->top_right_child && GTK_WIDGET_VISIBLE (xpaned->top_right_child) &&
-               xpaned->bottom_left_child && GTK_WIDGET_VISIBLE (xpaned->bottom_left_child) &&
-               xpaned->bottom_right_child && GTK_WIDGET_VISIBLE (xpaned->bottom_right_child))
+       if (xpaned->top_left_child && gtk_widget_get_visible (xpaned->top_left_child) &&
+               xpaned->top_right_child && gtk_widget_get_visible (xpaned->top_right_child) &&
+               xpaned->bottom_left_child && gtk_widget_get_visible (xpaned->bottom_left_child) &&
+               xpaned->bottom_right_child && gtk_widget_get_visible (xpaned->bottom_right_child))
        {
                gdk_window_show (xpaned->handle_east);
                gdk_window_show (xpaned->handle_west);
@@ -1325,11 +1324,11 @@ static gboolean gtk_xpaned_expose (GtkWidget* widget,
        /* I want the handle-"thickness" to be at least 3 */
        g_assert (handle_size >= 3);
 
-       if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget) &&
-               xpaned->top_left_child && GTK_WIDGET_VISIBLE (xpaned->top_left_child) &&
-               xpaned->top_right_child && GTK_WIDGET_VISIBLE (xpaned->top_right_child) &&
-               xpaned->bottom_left_child && GTK_WIDGET_VISIBLE (xpaned->bottom_left_child) &&
-               xpaned->bottom_right_child && GTK_WIDGET_VISIBLE (xpaned->bottom_right_child))
+       if (gtk_widget_get_visible (widget) && gtk_widget_get_mapped (widget) &&
+               xpaned->top_left_child && gtk_widget_get_visible (xpaned->top_left_child) &&
+               xpaned->top_right_child && gtk_widget_get_visible (xpaned->top_right_child) &&
+               xpaned->bottom_left_child && gtk_widget_get_visible (xpaned->bottom_left_child) &&
+               xpaned->bottom_right_child && gtk_widget_get_visible (xpaned->bottom_right_child))
     {
                GtkStateType state;
 
@@ -1338,7 +1337,7 @@ static gboolean gtk_xpaned_expose (GtkWidget* widget,
                else if (xpaned->handle_prelit)
                        state = GTK_STATE_PRELIGHT;
                else
-                       state = GTK_WIDGET_STATE (widget);
+                       state = gtk_widget_get_state (widget);
 
                horizontalClipArea.x = xpaned->handle_pos_west.x;
                horizontalClipArea.y = xpaned->handle_pos_west.y;
@@ -1930,7 +1929,7 @@ static void gtk_xpaned_remove (GtkContainer* container, GtkWidget* widget)
        gboolean was_visible;
 
        xpaned = GTK_XPANED (container);
-       was_visible = GTK_WIDGET_VISIBLE (widget);
+       was_visible = gtk_widget_get_visible (widget);
 
        if (xpaned->top_left_child == widget)
        {
@@ -1938,7 +1937,7 @@ static void gtk_xpaned_remove (GtkContainer* container, GtkWidget* widget)
 
                xpaned->top_left_child = NULL;
 
-               if (was_visible && GTK_WIDGET_VISIBLE (container))
+               if (was_visible && gtk_widget_get_visible (GTK_WIDGET (container)))
                        gtk_widget_queue_resize (GTK_WIDGET (container));
        }
        else if (xpaned->top_right_child == widget)
@@ -1947,7 +1946,7 @@ static void gtk_xpaned_remove (GtkContainer* container, GtkWidget* widget)
 
                xpaned->top_right_child = NULL;
 
-               if (was_visible && GTK_WIDGET_VISIBLE (container))
+               if (was_visible && gtk_widget_get_visible (GTK_WIDGET (container)))
                        gtk_widget_queue_resize (GTK_WIDGET (container));
        }
        else if (xpaned->bottom_left_child == widget)
@@ -1956,7 +1955,7 @@ static void gtk_xpaned_remove (GtkContainer* container, GtkWidget* widget)
 
                xpaned->bottom_left_child = NULL;
 
-               if (was_visible && GTK_WIDGET_VISIBLE (container))
+               if (was_visible && gtk_widget_get_visible (GTK_WIDGET (container)))
                        gtk_widget_queue_resize (GTK_WIDGET (container));
        }
        else if (xpaned->bottom_right_child == widget)
@@ -1965,7 +1964,7 @@ static void gtk_xpaned_remove (GtkContainer* container, GtkWidget* widget)
 
                xpaned->bottom_right_child = NULL;
 
-               if (was_visible && GTK_WIDGET_VISIBLE (container))
+               if (was_visible && gtk_widget_get_visible (GTK_WIDGET (container)))
                        gtk_widget_queue_resize (GTK_WIDGET (container));
        }
        else
@@ -2668,7 +2667,7 @@ static GtkWidget* xpaned_get_focus_widget (GtkXPaned* xpaned)
        GtkWidget* toplevel;
 
        toplevel = gtk_widget_get_toplevel (GTK_WIDGET (xpaned));
-       if (GTK_WIDGET_TOPLEVEL (toplevel))
+       if (gtk_widget_is_toplevel (toplevel))
                return GTK_WINDOW (toplevel)->focus_widget;
 
        return NULL;
@@ -3059,7 +3058,7 @@ static void gtk_xpaned_restore_focus (GtkXPaned* xpaned)
        if (gtk_widget_is_focus (GTK_WIDGET (xpaned)))
        {
                if (xpaned->priv->saved_focus &&
-                       GTK_WIDGET_SENSITIVE (xpaned->priv->saved_focus))
+                       gtk_widget_get_sensitive (xpaned->priv->saved_focus))
                {
                        gtk_widget_grab_focus (xpaned->priv->saved_focus);
                }
diff --git a/lib/tukey/README b/lib/tukey/README
new file mode 100644 (file)
index 0000000..e427872
--- /dev/null
@@ -0,0 +1 @@
+This is not part of the GNU PSPP program, but is used with GNU PSPP.
diff --git a/lib/tukey/automake.mk b/lib/tukey/automake.mk
new file mode 100644 (file)
index 0000000..85bcd62
--- /dev/null
@@ -0,0 +1,11 @@
+## Process this file with automake to produce Makefile.in  -*- makefile -*-
+
+noinst_LTLIBRARIES += lib/tukey/libtukey.la
+
+lib_tukey_libtukey_la_SOURCES = \
+       lib/tukey/ptukey.c \
+       lib/tukey/qtukey.c \
+       lib/tukey/tukey.h
+
+EXTRA_DIST += lib/tukey/README 
+
diff --git a/lib/tukey/ptukey.c b/lib/tukey/ptukey.c
new file mode 100644 (file)
index 0000000..c86ef23
--- /dev/null
@@ -0,0 +1,486 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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/>.
+*/
+
+/* This file is taken from the R project source code, and modified.
+   The original copyright notice is reproduced below: */
+
+/*
+ *  Mathlib : A C Library of Special Functions
+ *  Copyright (C) 1998       Ross Ihaka
+ *  Copyright (C) 2000--2007 The R Development Core Team
+ *
+ *  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 2 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, a copy is available at
+ *  http://www.r-project.org/Licenses/
+ *
+ *  SYNOPSIS
+ *
+ *    #include <Rmath.h>
+ *    double ptukey(q, rr, cc, df, lower_tail, log_p);
+ *
+ *  DESCRIPTION
+ *
+ *    Computes the probability that the maximum of rr studentized
+ *    ranges, each based on cc means and with df degrees of freedom
+ *    for the standard error, is less than q.
+ *
+ *    The algorithm is based on that of the reference.
+ *
+ *  REFERENCE
+ *
+ *    Copenhaver, Margaret Diponzio & Holland, Burt S.
+ *    Multiple comparisons of simple effects in
+ *    the two-way analysis of variance with fixed effects.
+ *    Journal of Statistical Computation and Simulation,
+ *    Vol.30, pp.1-15, 1988.
+ */
+
+
+#include <config.h>
+
+#include "libpspp/compiler.h"
+#include "tukey.h"
+
+#include <gsl/gsl_sf_gamma.h>
+#include <gsl/gsl_cdf.h>
+#include <assert.h>
+#include <math.h>
+
+#define R_D__0 (log_p ? ML_NEGINF : 0.)                /* 0 */
+#define R_D__1 (log_p ? 0. : 1.)                       /* 1 */
+#define R_DT_0 (lower_tail ? R_D__0 : R_D__1)          /* 0 */
+#define R_DT_1 (lower_tail ? R_D__1 : R_D__0)          /* 1 */
+
+#define R_D_val(x)     (log_p  ? log(x) : (x))         /*  x  in pF(x,..) */
+#define R_D_Clog(p)    (log_p  ? log1p(-(p)) : (0.5 - (p) + 0.5)) /* [log](1-p) */
+#define R_DT_val(x)    (lower_tail ? R_D_val(x)  : R_D_Clog(x))
+
+
+#define ME_PRECISION   8
+
+
+static inline double 
+pnorm(double x, double mu, double sigma, int lower_tail, int log_p)
+{
+  assert (lower_tail == 1);
+  assert (log_p == 0);
+  assert (sigma == 1.0);
+  
+  return gsl_cdf_gaussian_P (x - mu, sigma);
+}
+
+
+static double
+wprob (double w, double rr, double cc)
+{
+  const double M_1_SQRT_2PI = 1 / sqrt (2 * M_PI);
+
+
+/*  wprob() :
+
+       This function calculates probability integral of Hartley's
+       form of the range.
+
+       w     = value of range
+       rr    = no. of rows or groups
+       cc    = no. of columns or treatments
+       ir    = error flag = 1 if pr_w probability > 1
+       pr_w = returned probability integral from (0, w)
+
+       program will not terminate if ir is raised.
+
+       bb = upper limit of legendre integration
+       iMax = maximum acceptable value of integral
+       nleg = order of legendre quadrature
+       ihalf = int ((nleg + 1) / 2)
+       wlar = value of range above which wincr1 intervals are used to
+              calculate second part of integral,
+              else wincr2 intervals are used.
+       C1, C2, C3 = values which are used as cutoffs for terminating
+       or modifying a calculation.
+
+       M_1_SQRT_2PI = 1 / sqrt(2 * pi);  from abramowitz & stegun, p. 3.
+       M_SQRT2 = sqrt(2)
+       xleg = legendre 12-point nodes
+       aleg = legendre 12-point coefficients
+ */
+#define nleg   12
+#define ihalf  6
+
+  /* looks like this is suboptimal for double precision.
+     (see how C1-C3 are used) <MM>
+   */
+  /* const double iMax  = 1.; not used if = 1 */
+  static const double C1 = -30.;
+  static const double C2 = -50.;
+  static const double C3 = 60.;
+  static const double bb = 8.;
+  static const double wlar = 3.;
+  static const double wincr1 = 2.;
+  static const double wincr2 = 3.;
+  static const double xleg[ihalf] = {
+    0.981560634246719250690549090149,
+    0.904117256370474856678465866119,
+    0.769902674194304687036893833213,
+    0.587317954286617447296702418941,
+    0.367831498998180193752691536644,
+    0.125233408511468915472441369464
+  };
+  static const double aleg[ihalf] = {
+    0.047175336386511827194615961485,
+    0.106939325995318430960254718194,
+    0.160078328543346226334652529543,
+    0.203167426723065921749064455810,
+    0.233492536538354808760849898925,
+    0.249147045813402785000562436043
+  };
+  double a, ac, pr_w, b, binc, blb, c, cc1,
+    pminus, pplus, qexpo, qsqz, rinsum, wi, wincr, xx;
+  long double bub, einsum, elsum;
+  int j, jj;
+
+
+  qsqz = w * 0.5;
+
+  /* if w >= 16 then the integral lower bound (occurs for c=20) */
+  /* is 0.99999999999995 so return a value of 1. */
+
+  if (qsqz >= bb)
+    return 1.0;
+
+  /* find (f(w/2) - 1) ^ cc */
+  /* (first term in integral of hartley's form). */
+
+  pr_w = 2 * pnorm (qsqz, 0., 1., 1, 0) - 1.;  /* erf(qsqz / M_SQRT2) */
+  /* if pr_w ^ cc < 2e-22 then set pr_w = 0 */
+  if (pr_w >= exp (C2 / cc))
+    pr_w = pow (pr_w, cc);
+  else
+    pr_w = 0.0;
+
+  /* if w is large then the second component of the */
+  /* integral is small, so fewer intervals are needed. */
+
+  if (w > wlar)
+    wincr = wincr1;
+  else
+    wincr = wincr2;
+
+  /* find the integral of second term of hartley's form */
+  /* for the integral of the range for equal-length */
+  /* intervals using legendre quadrature.  limits of */
+  /* integration are from (w/2, 8).  two or three */
+  /* equal-length intervals are used. */
+
+  /* blb and bub are lower and upper limits of integration. */
+
+  blb = qsqz;
+  binc = (bb - qsqz) / wincr;
+  bub = blb + binc;
+  einsum = 0.0;
+
+  /* integrate over each interval */
+
+  cc1 = cc - 1.0;
+  for (wi = 1; wi <= wincr; wi++)
+    {
+      elsum = 0.0;
+      a = 0.5 * (bub + blb);
+
+      /* legendre quadrature with order = nleg */
+
+      b = 0.5 * (bub - blb);
+
+      for (jj = 1; jj <= nleg; jj++)
+       {
+         if (ihalf < jj)
+           {
+             j = (nleg - jj) + 1;
+             xx = xleg[j - 1];
+           }
+         else
+           {
+             j = jj;
+             xx = -xleg[j - 1];
+           }
+         c = b * xx;
+         ac = a + c;
+
+         /* if exp(-qexpo/2) < 9e-14, */
+         /* then doesn't contribute to integral */
+
+         qexpo = ac * ac;
+         if (qexpo > C3)
+           break;
+
+         pplus = 2 * pnorm (ac, 0., 1., 1, 0);
+         pminus = 2 * pnorm (ac, w, 1., 1, 0);
+
+         /* if rinsum ^ (cc-1) < 9e-14, */
+         /* then doesn't contribute to integral */
+
+         rinsum = (pplus * 0.5) - (pminus * 0.5);
+         if (rinsum >= exp (C1 / cc1))
+           {
+             rinsum =
+               (aleg[j - 1] * exp (-(0.5 * qexpo))) * pow (rinsum, cc1);
+             elsum += rinsum;
+           }
+       }
+      elsum *= (((2.0 * b) * cc) * M_1_SQRT_2PI);
+      einsum += elsum;
+      blb = bub;
+      bub += binc;
+    }
+
+  /* if pr_w ^ rr < 9e-14, then return 0 */
+  pr_w = einsum + pr_w;
+  if (pr_w <= exp (C1 / rr))
+    return 0.;
+
+  pr_w = pow (pr_w, rr);
+  if (pr_w >= 1.)              /* 1 was iMax was eps */
+    return 1.;
+  return pr_w;
+}                              /* wprob() */
+
+double
+ptukey (double q, double rr, double cc, double df, int lower_tail, int log_p)
+{
+  const double ML_NEGINF = -1.0 / 0.0;
+/*  function ptukey() [was qprob() ]:
+
+       q = value of studentized range
+       rr = no. of rows or groups
+       cc = no. of columns or treatments
+       df = degrees of freedom of error term
+       ir[0] = error flag = 1 if wprob probability > 1
+       ir[1] = error flag = 1 if qprob probability > 1
+
+       qprob = returned probability integral over [0, q]
+
+       The program will not terminate if ir[0] or ir[1] are raised.
+
+       All references in wprob to Abramowitz and Stegun
+       are from the following reference:
+
+       Abramowitz, Milton and Stegun, Irene A.
+       Handbook of Mathematical Functions.
+       New York:  Dover publications, Inc. (1970).
+
+       All constants taken from this text are
+       given to 25 significant digits.
+
+       nlegq = order of legendre quadrature
+       ihalfq = int ((nlegq + 1) / 2)
+       eps = max. allowable value of integral
+       eps1 & eps2 = values below which there is
+                     no contribution to integral.
+
+       d.f. <= dhaf:   integral is divided into ulen1 length intervals.  else
+       d.f. <= dquar:  integral is divided into ulen2 length intervals.  else
+       d.f. <= deigh:  integral is divided into ulen3 length intervals.  else
+       d.f. <= dlarg:  integral is divided into ulen4 length intervals.
+
+       d.f. > dlarg:   the range is used to calculate integral.
+
+       M_LN2 = log(2)
+
+       xlegq = legendre 16-point nodes
+       alegq = legendre 16-point coefficients
+
+       The coefficients and nodes for the legendre quadrature used in
+       qprob and wprob were calculated using the algorithms found in:
+
+       Stroud, A. H. and Secrest, D.
+       Gaussian Quadrature Formulas.
+       Englewood Cliffs,
+       New Jersey:  Prentice-Hall, Inc, 1966.
+
+       All values matched the tables (provided in same reference)
+       to 30 significant digits.
+
+       f(x) = .5 + erf(x / sqrt(2)) / 2      for x > 0
+
+       f(x) = erfc( -x / sqrt(2)) / 2        for x < 0
+
+       where f(x) is standard normal c. d. f.
+
+       if degrees of freedom large, approximate integral
+       with range distribution.
+ */
+#define nlegq  16
+#define ihalfq 8
+
+/*  const double eps = 1.0; not used if = 1 */
+  static const double eps1 = -30.0;
+  static const double eps2 = 1.0e-14;
+  static const double dhaf = 100.0;
+  static const double dquar = 800.0;
+  static const double deigh = 5000.0;
+  static const double dlarg = 25000.0;
+  static const double ulen1 = 1.0;
+  static const double ulen2 = 0.5;
+  static const double ulen3 = 0.25;
+  static const double ulen4 = 0.125;
+  static const double xlegq[ihalfq] = {
+    0.989400934991649932596154173450,
+    0.944575023073232576077988415535,
+    0.865631202387831743880467897712,
+    0.755404408355003033895101194847,
+    0.617876244402643748446671764049,
+    0.458016777657227386342419442984,
+    0.281603550779258913230460501460,
+    0.950125098376374401853193354250e-1
+  };
+  static const double alegq[ihalfq] = {
+    0.271524594117540948517805724560e-1,
+    0.622535239386478928628438369944e-1,
+    0.951585116824927848099251076022e-1,
+    0.124628971255533872052476282192,
+    0.149595988816576732081501730547,
+    0.169156519395002538189312079030,
+    0.182603415044923588866763667969,
+    0.189450610455068496285396723208
+  };
+  double ans, f2, f21, f2lf, ff4, otsum, qsqz, rotsum, t1, twa1, ulen, wprb;
+  int i, j, jj;
+
+#ifdef IEEE_754
+  abort (! (ISNAN (q) || ISNAN (rr) || ISNAN (cc) || ISNAN (df)));
+#endif
+
+  if (q <= 0)
+    return R_DT_0;
+
+  /* df must be > 1 */
+  /* there must be at least two values */
+  assert (! (df < 2 || rr < 1 || cc < 2));
+
+  if (!isfinite (q))
+    return R_DT_1;
+
+  if (df > dlarg)
+    return R_DT_val (wprob (q, rr, cc));
+
+  /* calculate leading constant */
+
+  f2 = df * 0.5;
+  /* lgammafn(u) = log(gamma(u)) */
+  f2lf = ((f2 * log (df)) - (df * M_LN2)) - gsl_sf_lngamma (f2);
+  f21 = f2 - 1.0;
+
+  /* integral is divided into unit, half-unit, quarter-unit, or */
+  /* eighth-unit length intervals depending on the value of the */
+  /* degrees of freedom. */
+
+  ff4 = df * 0.25;
+  if (df <= dhaf)
+    ulen = ulen1;
+  else if (df <= dquar)
+    ulen = ulen2;
+  else if (df <= deigh)
+    ulen = ulen3;
+  else
+    ulen = ulen4;
+
+  f2lf += log (ulen);
+
+  /* integrate over each subinterval */
+
+  ans = 0.0;
+
+  for (i = 1; i <= 50; i++)
+    {
+      otsum = 0.0;
+
+      /* legendre quadrature with order = nlegq */
+      /* nodes (stored in xlegq) are symmetric around zero. */
+
+      twa1 = (2 * i - 1) * ulen;
+
+      for (jj = 1; jj <= nlegq; jj++)
+       {
+         if (ihalfq < jj)
+           {
+             j = jj - ihalfq - 1;
+             t1 = (f2lf + (f21 * log (twa1 + (xlegq[j] * ulen))))
+               - (((xlegq[j] * ulen) + twa1) * ff4);
+           }
+         else
+           {
+             j = jj - 1;
+             t1 = (f2lf + (f21 * log (twa1 - (xlegq[j] * ulen))))
+               + (((xlegq[j] * ulen) - twa1) * ff4);
+
+           }
+
+         /* if exp(t1) < 9e-14, then doesn't contribute to integral */
+         if (t1 >= eps1)
+           {
+             if (ihalfq < jj)
+               {
+                 qsqz = q * sqrt (((xlegq[j] * ulen) + twa1) * 0.5);
+               }
+             else
+               {
+                 qsqz = q * sqrt (((-(xlegq[j] * ulen)) + twa1) * 0.5);
+               }
+
+             /* call wprob to find integral of range portion */
+
+             wprb = wprob (qsqz, rr, cc);
+             rotsum = (wprb * alegq[j]) * exp (t1);
+             otsum += rotsum;
+           }
+         /* end legendre integral for interval i */
+         /* L200: */
+       }
+
+      /* if integral for interval i < 1e-14, then stop.
+       * However, in order to avoid small area under left tail,
+       * at least  1 / ulen  intervals are calculated.
+       */
+      if (i * ulen >= 1.0 && otsum <= eps2)
+       break;
+
+      /* end of interval i */
+      /* L330: */
+
+      ans += otsum;
+    }
+
+  assert (otsum <= eps2); /* not converged */
+
+  if (ans > 1.)
+    ans = 1.;
+  return R_DT_val (ans);
+}
+
+
+
diff --git a/lib/tukey/qtukey.c b/lib/tukey/qtukey.c
new file mode 100644 (file)
index 0000000..08253df
--- /dev/null
@@ -0,0 +1,253 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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/>.
+*/
+
+/* This file is taken from the R project source code, and modified.
+   The original copyright notice is reproduced below: */
+
+/*
+ *  Mathlib : A C Library of Special Functions
+ *  Copyright (C) 1998              Ross Ihaka
+ *  Copyright (C) 2000--2005 The R Development Core Team
+ *  based in part on AS70 (C) 1974 Royal Statistical Society
+ *
+ *  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 2 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, a copy is available at
+ *  http://www.r-project.org/Licenses/
+ *
+ *  SYNOPSIS
+ *
+ *     #include <Rmath.h>
+ *     double qtukey(p, rr, cc, df, lower_tail, log_p);
+ *
+ *  DESCRIPTION
+ *
+ *     Computes the quantiles of the maximum of rr studentized
+ *     ranges, each based on cc means and with df degrees of freedom
+ *     for the standard error, is less than q.
+ *
+ *     The algorithm is based on that of the reference.
+ *
+ *  REFERENCE
+ *
+ *     Copenhaver, Margaret Diponzio & Holland, Burt S.
+ *     Multiple comparisons of simple effects in
+ *     the two-way analysis of variance with fixed effects.
+ *     Journal of Statistical Computation and Simulation,
+ *     Vol.30, pp.1-15, 1988.
+ */
+
+#include <config.h>
+
+#include "tukey.h"
+
+#include <assert.h>
+#include <math.h>
+
+#define TRUE (1)
+#define FALSE (0)
+
+#define ML_POSINF      (1.0 / 0.0)
+#define ML_NEGINF      (-1.0 / 0.0)
+
+#define R_D_Lval(p)    (lower_tail ? (p) : (0.5 - (p) + 0.5))  /*  p  */
+
+#define R_DT_qIv(p)    (log_p ? (lower_tail ? exp(p) : - expm1(p)) \
+                              : R_D_Lval(p))
+
+
+static double fmax2(double x, double y)
+{
+#ifdef IEEE_754
+       if (ISNAN(x) || ISNAN(y))
+               return x + y;
+#endif
+       return (x < y) ? y : x;
+}
+
+
+#define R_Q_P01_boundaries(p, _LEFT_, _RIGHT_)         \
+    if (log_p) {                                       \
+      assert (p <= 0);                                 \
+       if(p == 0) /* upper bound*/                     \
+           return lower_tail ? _RIGHT_ : _LEFT_;       \
+       if(p == ML_NEGINF)                              \
+           return lower_tail ? _LEFT_ : _RIGHT_;       \
+    }                                                  \
+    else { /* !log_p */                                        \
+      assert (p >= 0 && p <= 1);                       \
+       if(p == 0)                                      \
+           return lower_tail ? _LEFT_ : _RIGHT_;       \
+       if(p == 1)                                      \
+           return lower_tail ? _RIGHT_ : _LEFT_;       \
+    }
+
+
+/* qinv() :
+ *     this function finds percentage point of the studentized range
+ *     which is used as initial estimate for the secant method.
+ *     function is adapted from portion of algorithm as 70
+ *     from applied statistics (1974) ,vol. 23, no. 1
+ *     by odeh, r. e. and evans, j. o.
+ *
+ *       p = percentage point
+ *       c = no. of columns or treatments
+ *       v = degrees of freedom
+ *       qinv = returned initial estimate
+ *
+ *     vmax is cutoff above which degrees of freedom
+ *     is treated as infinity.
+ */
+
+static double qinv(double p, double c, double v)
+{
+    static const double p0 = 0.322232421088;
+    static const double q0 = 0.993484626060e-01;
+    static const double p1 = -1.0;
+    static const double q1 = 0.588581570495;
+    static const double p2 = -0.342242088547;
+    static const double q2 = 0.531103462366;
+    static const double p3 = -0.204231210125;
+    static const double q3 = 0.103537752850;
+    static const double p4 = -0.453642210148e-04;
+    static const double q4 = 0.38560700634e-02;
+    static const double c1 = 0.8832;
+    static const double c2 = 0.2368;
+    static const double c3 = 1.214;
+    static const double c4 = 1.208;
+    static const double c5 = 1.4142;
+    static const double vmax = 120.0;
+
+    double ps, q, t, yi;
+
+    ps = 0.5 - 0.5 * p;
+    yi = sqrt (log (1.0 / (ps * ps)));
+    t = yi + (((( yi * p4 + p3) * yi + p2) * yi + p1) * yi + p0)
+          / (((( yi * q4 + q3) * yi + q2) * yi + q1) * yi + q0);
+    if (v < vmax) t += (t * t * t + t) / v / 4.0;
+    q = c1 - c2 * t;
+    if (v < vmax) q += -c3 / v + c4 * t / v;
+    return t * (q * log (c - 1.0) + c5);
+}
+
+/*
+ *  Copenhaver, Margaret Diponzio & Holland, Burt S.
+ *  Multiple comparisons of simple effects in
+ *  the two-way analysis of variance with fixed effects.
+ *  Journal of Statistical Computation and Simulation,
+ *  Vol.30, pp.1-15, 1988.
+ *
+ *  Uses the secant method to find critical values.
+ *
+ *  p = confidence level (1 - alpha)
+ *  rr = no. of rows or groups
+ *  cc = no. of columns or treatments
+ *  df = degrees of freedom of error term
+ *
+ *  ir(1) = error flag = 1 if wprob probability > 1
+ *  ir(2) = error flag = 1 if ptukey probability > 1
+ *  ir(3) = error flag = 1 if convergence not reached in 50 iterations
+ *                    = 2 if df < 2
+ *
+ *  qtukey = returned critical value
+ *
+ *  If the difference between successive iterates is less than eps,
+ *  the search is terminated
+ */
+
+
+double qtukey(double p, double rr, double cc, double df,
+             int lower_tail, int log_p)
+{
+    static const double eps = 0.0001;
+    const int maxiter = 50;
+
+    double ans = 0.0, valx0, valx1, x0, x1, xabs;
+    int iter;
+
+#ifdef IEEE_754
+    if (ISNAN(p) || ISNAN(rr) || ISNAN(cc) || ISNAN(df)) {
+       ML_ERROR(ME_DOMAIN, "qtukey");
+       return p + rr + cc + df;
+    }
+#endif
+
+    /* df must be > 1 ; there must be at least two values */
+    assert (! (df < 2 || rr < 1 || cc < 2) );
+
+    R_Q_P01_boundaries (p, 0, ML_POSINF);
+
+    p = R_DT_qIv(p); /* lower_tail,non-log "p" */
+
+    /* Initial value */
+
+    x0 = qinv(p, cc, df);
+
+    /* Find prob(value < x0) */
+
+    valx0 = ptukey(x0, rr, cc, df, /*LOWER*/TRUE, /*LOG_P*/FALSE) - p;
+
+    /* Find the second iterate and prob(value < x1). */
+    /* If the first iterate has probability value */
+    /* exceeding p then second iterate is 1 less than */
+    /* first iterate; otherwise it is 1 greater. */
+
+    if (valx0 > 0.0)
+       x1 = fmax2(0.0, x0 - 1.0);
+    else
+       x1 = x0 + 1.0;
+    valx1 = ptukey(x1, rr, cc, df, /*LOWER*/TRUE, /*LOG_P*/FALSE) - p;
+
+    /* Find new iterate */
+
+    for(iter=1 ; iter < maxiter ; iter++) {
+       ans = x1 - ((valx1 * (x1 - x0)) / (valx1 - valx0));
+       valx0 = valx1;
+
+       /* New iterate must be >= 0 */
+
+       x0 = x1;
+       if (ans < 0.0) {
+           ans = 0.0;
+           valx1 = -p;
+       }
+       /* Find prob(value < new iterate) */
+
+       valx1 = ptukey(ans, rr, cc, df, /*LOWER*/TRUE, /*LOG_P*/FALSE) - p;
+       x1 = ans;
+
+       /* If the difference between two successive */
+       /* iterates is less than eps, stop */
+
+       xabs = fabs(x1 - x0);
+       if (xabs < eps)
+           return ans;
+    }
+
+    /* The process did not converge in 'maxiter' iterations */
+    assert (0);
+    return ans;
+}
diff --git a/lib/tukey/tukey.h b/lib/tukey/tukey.h
new file mode 100644 (file)
index 0000000..69050e8
--- /dev/null
@@ -0,0 +1,25 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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/>.
+*/
+
+#ifndef TUKEY_H
+#define TUKEY_H 1
+
+double qtukey(double p, double rr, double cc, double df,  int lower_tail, int log_p);
+
+double ptukey (double q, double rr, double cc, double df, int lower_tail, int log_p);
+
+#endif
index 143eb549e1a784c4df7b4c7b89fa644118f1056e..77b7682b3e29c96178034a60797887c78c2dd208 100644 (file)
@@ -727,6 +727,21 @@ CODE:
  OUTPUT:
 RETVAL
 
+SV *
+get_case_cnt (sfr)
+ struct sysreader_info *sfr;
+CODE:
+ SV *ret;
+ casenumber n = casereader_get_case_cnt (sfr->reader);
+ if (n == CASENUMBER_MAX)
+  ret = &PL_sv_undef;
+ else 
+  ret = newSViv (n);
+ RETVAL = ret;
+ OUTPUT:
+RETVAL
+
+
 
 void
 get_next_case (sfr)
index a99c77db275aed0c4345893be575669e5c9c0573..7d077992bd4ad2eef11caee90e663353021e4223 100644 (file)
@@ -483,6 +483,13 @@ Open is used to read data from an existing system file.
 It creates and returns a PSPP::Reader object which can be used to read 
 data and dictionary information from C<filename>.
 
+=head3 get_case_cnt ()
+
+Returns the number of cases in a open system file.  Some files
+do not store the number of cases.  In these instances undef
+will be returned.  Therefore, then programmer must check that the
+returned value is not undef before using it.
+
 =cut
 
 sub get_dict
index 6e267f6fb8f535c5bfff0aedd0629f555161639e..a7fb9578da8dc90efbe00dbb103c9c6b5057db30 100644 (file)
@@ -8,7 +8,7 @@
 
 # change 'tests => 1' to 'tests => last_test_to_print';
 
-use Test::More tests => 36;
+use Test::More tests => 37;
 use Text::Diff;
 use File::Temp qw/ tempfile tempdir /;
 BEGIN { use_ok('PSPP') };
@@ -605,5 +605,18 @@ colour =>blue, pink, violet
 nationality =>foreign
 size =>large
 EOF
+}
+
+
+# Test of the get_case_cnt function
+{
+ my $tempdir = tempdir( CLEANUP => 1 );
+
+ generate_sav_file ("$tempdir/in.sav", "$tempdir");
+
+ my $sf = PSPP::Reader->open ("$tempdir/in.sav");
+
+ my $n = $sf->get_case_cnt ();
 
+ ok ($n == 5, "Case count");
 }
index 92015ef95cd8b579d7d543a8d69c70c8e2e4e890..e0276a30916cd617b5cc99a43580258c09a3bc18 100644 (file)
@@ -15,6 +15,7 @@ XGETTEXT_OPTIONS = \
        --package-name=$(PACKAGE) \
        --package-version=$(VERSION) \
        --msgid-bugs-address=$(MSGID_BUGS_ADDRESS) \
+        --from-code=UTF-8 \
        --add-comments='TRANSLATORS:'
 
 $(POTFILE): $(TRANSLATABLE_FILES) $(UI_FILES)
index 3058e37e53de883c2c56ff65fddaf23876d0db3b..8c8f25230a5fe5d4e52573402e837a629619c4a0 100644 (file)
--- a/po/ca.po
+++ b/po/ca.po
@@ -7,12 +7,13 @@
 # Javier Gómez Serrano, 2009.
 # Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>, 2010.
 # Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>, 2011.
+# Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>, 2011.
 msgid ""
 msgstr ""
-"Project-Id-Version: pspp-0.7.7\n"
+"Project-Id-Version: pspp-0.7.8\n"
 "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
-"POT-Creation-Date: 2011-03-24 20:36-0700\n"
-"PO-Revision-Date: 2011-05-02 21:52+0200\n"
+"POT-Creation-Date: 2011-05-04 06:57-0700\n"
+"PO-Revision-Date: 2011-08-17 11:48+0200\n"
 "Last-Translator: Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>\n"
 "Language-Team: Catalan <ca@dodds.net>\n"
 "Language: ca\n"
@@ -25,38 +26,38 @@ msgstr ""
 msgid "Sorry. The help system hasn't yet been implemented."
 msgstr "Disculpeu. El sistema d'ajuda encara no ha estat implementat."
 
-#: src/ui/gui/psppire-buttonbox.c:275 src/ui/gui/psppire-buttonbox.c:437
+#: src/ui/gui/psppire-buttonbox.c:313 src/ui/gui/psppire-buttonbox.c:469
 msgid "Continue"
 msgstr "Continuar"
 
-#: src/ui/gui/psppire-buttonbox.c:435
+#: src/ui/gui/psppire-buttonbox.c:467
 msgid "OK"
 msgstr "OK"
 
-#: src/ui/gui/psppire-buttonbox.c:436
+#: src/ui/gui/psppire-buttonbox.c:468
 msgid "Go To"
 msgstr "Anar a"
 
-#: src/ui/gui/psppire-buttonbox.c:438
+#: src/ui/gui/psppire-buttonbox.c:470
 msgid "Cancel"
 msgstr "Cancel·lar"
 
-#: src/ui/gui/psppire-buttonbox.c:439
+#: src/ui/gui/psppire-buttonbox.c:471
 msgid "Help"
 msgstr "Ajuda"
 
-#: src/ui/gui/psppire-buttonbox.c:440
+#: src/ui/gui/psppire-buttonbox.c:472
 msgid "Reset"
 msgstr "Reiniciar"
 
-#: src/ui/gui/psppire-buttonbox.c:441
+#: src/ui/gui/psppire-buttonbox.c:473
 msgid "Paste"
 msgstr "Enganxa"
 
 #: src/ui/gui/psppire-dictview.c:466 src/language/dictionary/split-file.c:82
 #: src/language/dictionary/sys-file-info.c:149
-#: src/language/dictionary/sys-file-info.c:334
-#: src/language/dictionary/sys-file-info.c:658
+#: src/language/dictionary/sys-file-info.c:332
+#: src/language/dictionary/sys-file-info.c:646
 #: src/language/stats/descriptives.c:895
 #: src/language/data-io/data-parser.c:683
 #: src/language/data-io/data-parser.c:722 src/language/data-io/print.c:403
@@ -67,7 +68,7 @@ msgstr "Variable"
 msgid "Prefer variable labels"
 msgstr "Prefereixo les etiquetes de variable"
 
-#: src/ui/gui/psppire-var-view.c:193
+#: src/ui/gui/psppire-var-view.c:192
 #, c-format
 msgid "Var%d"
 msgstr "Var%d"
@@ -111,7 +112,7 @@ msgstr "Almenys un cas a la lectura de dades tenia un valor de ponderació que 
 msgid "CSV file"
 msgstr "arxiu CSV"
 
-#: src/data/csv-file-writer.c:163 src/data/sys-file-writer.c:219
+#: src/data/csv-file-writer.c:163 src/data/sys-file-writer.c:225
 #, c-format
 msgid "Error opening `%s' for writing as a system file: %s."
 msgstr "Error en obrir `%s' per gravar com arxiu de sistema: %s."
@@ -244,6 +245,17 @@ msgstr "Nombre de dia de la setmana%f no està entre 1 i 7."
 msgid "Month number %f is not between 1 and 12."
 msgstr "Nombre de mes %f no està entre 1 i 12."
 
+#: src/data/dataset-reader.c:54
+#, c-format
+msgid "Cannot read from dataset %s because no dictionary or data has been written to it yet."
+msgstr "No es pot llegir de l'arxius de dades actiu %s perquè no s'ha omplert encara amb cap diccionari o dades."
+
+#. TRANSLATORS: this fragment will be interpolated into
+#. messages in fh_lock() that identify types of files.
+#: src/data/dataset-writer.c:66 src/language/data-io/file-handle.q:182
+msgid "dataset"
+msgstr "arxiu de dades"
+
 #: src/data/dict-class.c:52
 msgid "ordinary"
 msgstr "ordinàri/a"
@@ -256,26 +268,30 @@ msgstr "sistema"
 msgid "scratch"
 msgstr "zero"
 
-#: src/data/dictionary.c:1007
+#: src/data/dictionary.c:1003
 msgid "At least one case in the data file had a weight value that was user-missing, system-missing, zero, or negative.  These case(s) were ignored."
 msgstr "Almenys un cas a l'arxiu de dades tenia un valor de ponderació que és perdut d'usuari, de sistema, zero o negatiu. Aquest(s) cas(os) van ser ignorat(s)."
 
-#: src/data/dictionary.c:1333
+#: src/data/dictionary.c:1329
 #, c-format
 msgid "Truncating document line to %d bytes."
 msgstr "Línia de document tallada a  %d bytes."
 
-#: src/data/file-handle-def.c:469
+#: src/data/file-handle-def.c:254
+msgid "active dataset"
+msgstr "arxiu de dades actiu"
+
+#: src/data/file-handle-def.c:465
 #, c-format
 msgid "Can't read from %s as a %s because it is already being read as a %s."
 msgstr "No es pot llegir de %s com una %s perquè ja està sent llegit com una %s."
 
-#: src/data/file-handle-def.c:473
+#: src/data/file-handle-def.c:469
 #, c-format
 msgid "Can't write to %s as a %s because it is already being written as a %s."
 msgstr "No es pot escriure en %s com un %s perquè ja està escrit com un %s."
 
-#: src/data/file-handle-def.c:480
+#: src/data/file-handle-def.c:476
 #, c-format
 msgid "Can't re-open %s as a %s."
 msgstr "No es pot tornar a obrir %s com a %s."
@@ -335,19 +351,19 @@ msgid "%s variables are not compatible with %s format %s."
 msgstr "Les variables %s no són compatibles amb %s format %s."
 
 #: src/data/format.c:412 src/data/sys-file-reader.c:1078
-#: src/ui/gui/psppire-var-store.c:629 src/ui/gui/compute.ui:503
+#: src/ui/gui/psppire-var-store.c:628 src/ui/gui/compute.ui:503
 #: src/ui/gui/var-sheet-dialogs.ui:139
 msgid "String"
 msgstr "Cadena"
 
 #: src/data/format.c:412 src/data/sys-file-reader.c:1078
-#: src/ui/gui/psppire-var-store.c:622 src/ui/gui/compute.ui:584
+#: src/ui/gui/psppire-var-store.c:621 src/ui/gui/compute.ui:584
 #: src/ui/gui/var-sheet-dialogs.ui:27
 msgid "Numeric"
 msgstr "Numèric"
 
-#: src/data/format.c:413 src/data/sys-file-reader.c:1663
-#: src/data/sys-file-reader.c:1665 src/language/xforms/recode.c:506
+#: src/data/format.c:413 src/data/sys-file-reader.c:1671
+#: src/data/sys-file-reader.c:1673 src/language/xforms/recode.c:506
 #: src/language/xforms/recode.c:507 src/language/xforms/recode.c:519
 #: src/language/xforms/recode.c:520
 #: src/language/dictionary/apply-dictionary.c:77
@@ -355,8 +371,8 @@ msgstr "Numèric"
 msgid "numeric"
 msgstr "numèric"
 
-#: src/data/format.c:413 src/data/sys-file-reader.c:1663
-#: src/data/sys-file-reader.c:1665 src/language/xforms/recode.c:506
+#: src/data/format.c:413 src/data/sys-file-reader.c:1671
+#: src/data/sys-file-reader.c:1673 src/language/xforms/recode.c:506
 #: src/language/xforms/recode.c:507 src/language/xforms/recode.c:519
 #: src/language/xforms/recode.c:520
 #: src/language/dictionary/apply-dictionary.c:77
@@ -383,7 +399,7 @@ msgstr "Error en obrir `%s' per a la lectura com a arxiu Gnumeric: %s."
 msgid "Invalid cell range `%s'"
 msgstr "Interval de cel·la `%s' invàlid"
 
-#: src/data/gnumeric-reader.c:522
+#: src/data/gnumeric-reader.c:521
 #, c-format
 msgid "Selected sheet or range of spreadsheet `%s' is empty."
 msgstr "El full o fulls de càlcul seleccionats `%s' és buit."
@@ -457,141 +473,141 @@ msgstr "Eliminant %s: %s."
 msgid "%s is not a valid name for a multiple response set.  Multiple response set names must begin with `$'."
 msgstr "%s no és un nom vàlid de variable per a un conjunt de resposta múltiple. Els conjunts de resposta múltiple han de començar amb `$'."
 
-#: src/data/por-file-reader.c:100
+#: src/data/por-file-reader.c:101
 #, c-format
 msgid "portable file %s corrupt at offset 0x%llx: "
 msgstr "l'arxiu portàtil %s és trencat a la posició 0x%llx: "
 
-#: src/data/por-file-reader.c:132
+#: src/data/por-file-reader.c:133
 #, c-format
 msgid "reading portable file %s at offset 0x%llx: "
 msgstr "Llegint l'arxiu portàtil %s en la posició 0x%llx: "
 
-#: src/data/por-file-reader.c:163
+#: src/data/por-file-reader.c:164
 #, c-format
 msgid "Error closing portable file `%s': %s."
 msgstr "Error en tancar l'arxiu portàtil `%s': %s."
 
-#: src/data/por-file-reader.c:215
+#: src/data/por-file-reader.c:216
 msgid "unexpected end of file"
 msgstr "fi d'arxiu inesperat"
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
-#: src/data/por-file-reader.c:274 src/data/por-file-writer.c:148
+#: src/data/por-file-reader.c:275 src/data/por-file-writer.c:148
 msgid "portable file"
 msgstr "arxiu portàtil"
 
-#: src/data/por-file-reader.c:282
+#: src/data/por-file-reader.c:283
 #, c-format
 msgid "An error occurred while opening `%s' for reading as a portable file: %s."
 msgstr "Error en obrir `%s' per a la lectura com a arxiu portàtil: %s."
 
-#: src/data/por-file-reader.c:303
+#: src/data/por-file-reader.c:304
 msgid "Data record expected."
 msgstr "Registre de dades esperat."
 
-#: src/data/por-file-reader.c:385
+#: src/data/por-file-reader.c:386
 msgid "Number expected."
 msgstr "Nombre esperat."
 
-#: src/data/por-file-reader.c:413
+#: src/data/por-file-reader.c:414
 msgid "Missing numeric terminator."
 msgstr "Manca de terminació numèrica."
 
-#: src/data/por-file-reader.c:436
+#: src/data/por-file-reader.c:437
 msgid "Invalid integer."
 msgstr "Nombre enter invàlid."
 
-#: src/data/por-file-reader.c:447 src/data/por-file-reader.c:467
+#: src/data/por-file-reader.c:448 src/data/por-file-reader.c:468
 #, c-format
 msgid "Bad string length %d."
 msgstr "Longitud de cadena %d invàlida."
 
-#: src/data/por-file-reader.c:530
+#: src/data/por-file-reader.c:531
 #, c-format
 msgid "%s: Not a portable file."
 msgstr "%s: No és un arxiu portàtil."
 
-#: src/data/por-file-reader.c:547
+#: src/data/por-file-reader.c:548
 #, c-format
 msgid "Unrecognized version code `%c'."
 msgstr "Codi de versió `%c' no reconegut."
 
-#: src/data/por-file-reader.c:556
+#: src/data/por-file-reader.c:557
 #, c-format
 msgid "Bad date string length %zu."
 msgstr "Longitud de cadena de dades %zu invàlida."
 
-#: src/data/por-file-reader.c:558
+#: src/data/por-file-reader.c:559
 #, c-format
 msgid "Bad time string length %zu."
 msgstr "Longitud de cadena de temps %zu invàlida."
 
-#: src/data/por-file-reader.c:600
+#: src/data/por-file-reader.c:601
 #, c-format
 msgid "%s: Bad format specifier byte (%d).  Variable will be assigned a default format."
 msgstr "%s: Byte especificador de format invàlid (%d). S'assignarà el format predeterminat a la variable."
 
-#: src/data/por-file-reader.c:621
+#: src/data/por-file-reader.c:622
 #, c-format
 msgid "Numeric variable %s has invalid format specifier %s."
 msgstr "La variable numèrica %s té una especificació de format invàlida %s."
 
-#: src/data/por-file-reader.c:625
+#: src/data/por-file-reader.c:626
 #, c-format
 msgid "String variable %s with width %d has invalid format specifier %s."
 msgstr "La variable en cadena %s amb longitud %d té una especificació de format invàlida %s."
 
-#: src/data/por-file-reader.c:649
+#: src/data/por-file-reader.c:650
 msgid "Expected variable count record."
 msgstr "Registre de recompte de variables esperat."
 
-#: src/data/por-file-reader.c:653
+#: src/data/por-file-reader.c:654
 #, c-format
 msgid "Invalid number of variables %d."
 msgstr "Número invàlid de variables: %d."
 
-#: src/data/por-file-reader.c:662
+#: src/data/por-file-reader.c:663
 #, c-format
 msgid "Weight variable name (%s) truncated."
 msgstr "Nom de la variable ponderada (%s) truncat."
 
-#: src/data/por-file-reader.c:677
+#: src/data/por-file-reader.c:678
 msgid "Expected variable record."
 msgstr "Registre de variable esperat."
 
-#: src/data/por-file-reader.c:681
+#: src/data/por-file-reader.c:682
 #, c-format
 msgid "Invalid variable width %d."
 msgstr "Amplada de la variable invàlida %d."
 
-#: src/data/por-file-reader.c:689
+#: src/data/por-file-reader.c:690
 #, c-format
 msgid "Invalid variable name `%s' in position %d."
 msgstr "Nom de la variable invàlid `%s' en la posició %d."
 
-#: src/data/por-file-reader.c:693 src/data/sys-file-reader.c:963
+#: src/data/por-file-reader.c:694 src/data/sys-file-reader.c:963
 #, c-format
 msgid "Bad width %d for variable %s."
 msgstr "Amplada %d incorrecte per a la variable %s."
 
-#: src/data/por-file-reader.c:707
+#: src/data/por-file-reader.c:708
 #, c-format
 msgid "Duplicate variable name %s in position %d renamed to %s."
 msgstr "Nom de la variable %s duplicat en la posició %d s'ha reanomenat a %s."
 
-#: src/data/por-file-reader.c:756
+#: src/data/por-file-reader.c:757
 #, c-format
 msgid "Weighting variable %s not present in dictionary."
 msgstr "La variable de ponderació %s no està al diccionari."
 
-#: src/data/por-file-reader.c:800
+#: src/data/por-file-reader.c:801
 #, c-format
 msgid "Unknown variable %s while parsing value labels."
 msgstr "Variable %s desconeguda mentre s'analitzaven les etiquetes de valor."
 
-#: src/data/por-file-reader.c:803
+#: src/data/por-file-reader.c:804
 #, c-format
 msgid "Cannot assign value labels to %s and %s, which have different variable types."
 msgstr "No es pot assignar etiquetes de valor a %s i %s, que tenen diferent tipus de variables."
@@ -611,25 +627,25 @@ msgstr "Error al obrir `%s' per a escriure com a arxiu  portàtil: %s."
 msgid "An I/O error occurred writing portable file `%s'."
 msgstr "Error E/S en escriure l'arxiu portàtil `%s'."
 
-#: src/data/psql-reader.c:46
+#: src/data/psql-reader.c:47
 msgid "Support for reading postgres databases was not compiled into this installation of PSPP"
 msgstr "El suport per a la lectura de les bases de dades postgres no va ser compilat en aquesta instal·lació de PSPP"
 
-#: src/data/psql-reader.c:239
+#: src/data/psql-reader.c:241
 msgid "Memory error whilst opening psql source"
 msgstr "Error de memòria al obrir la font psql"
 
-#: src/data/psql-reader.c:245
+#: src/data/psql-reader.c:247
 #, c-format
 msgid "Error opening psql source: %s."
 msgstr "Error obrint la font psql: %s."
 
-#: src/data/psql-reader.c:260
+#: src/data/psql-reader.c:262
 #, c-format
 msgid "Postgres server is version %s. Reading from versions earlier than 8.0 is not supported."
 msgstr "La versió del servidor Postgres és la %s. No es possible la lectura des de versions anteriors a la 8.0."
 
-#: src/data/psql-reader.c:280
+#: src/data/psql-reader.c:282
 msgid "Connection is unencrypted, but unencrypted connections have not been permitted."
 msgstr "La connexió no està xifrada, però les connexions sense xifrar no estan permeses."
 
@@ -644,17 +660,6 @@ msgstr "Error des de la font psql: %s."
 msgid "Unsupported OID %d.  SYSMIS values will be inserted."
 msgstr "OID %d no admès. Valors SYSMIS seran inserits."
 
-#: src/data/scratch-reader.c:54
-#, c-format
-msgid "Scratch file handle %s has not yet been written, using SAVE or another procedure, so it cannot yet be used for reading."
-msgstr "El manipulador de l'arxius de treball %s encara no s'ha escrit, utilitzant SAVE o altre procediment, de manera que encara no es pot llegir."
-
-#. TRANSLATORS: this fragment will be interpolated into
-#. messages in fh_lock() that identify types of files.
-#: src/data/scratch-writer.c:66 src/language/data-io/file-handle.q:186
-msgid "scratch file"
-msgstr "arxiu de treball"
-
 #: src/data/settings.c:384
 msgid "MXWARNS set to zero.  No further warnings will be given even when potentially problematic situations are encountered."
 msgstr "S'assigna zero a MXWARNS.  No es proporcionaran més avisos tot, i que podrien trobar-se situacions problemàtiques posteriors."
@@ -669,40 +674,36 @@ msgstr "Avisos activats de nou.  Es tindran en compte %d avisos abans d'abortar
 msgid "%s: Custom currency string `%s' does not contain exactly three periods or commas (or it contains both)."
 msgstr "%s: Cadena de moneda personalitzada '%s' no conté exactament tres punts o comes (o els conté ambdós)."
 
-#: src/data/short-names.c:52
-msgid "Variable suffix too large."
-msgstr "Sufix de la variable massa gran."
-
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
-#: src/data/sys-file-reader.c:323 src/data/sys-file-writer.c:207
+#: src/data/sys-file-reader.c:324 src/data/sys-file-writer.c:213
 msgid "system file"
 msgstr "arxiu de sistema"
 
-#: src/data/sys-file-reader.c:330
+#: src/data/sys-file-reader.c:331
 #, c-format
 msgid "Error opening `%s' for reading as a system file: %s."
 msgstr "Error en obrir `%s' per a la lectura com arxiu de sistema: %s."
 
-#: src/data/sys-file-reader.c:387 tests/dissect-sysfile.c:155
+#: src/data/sys-file-reader.c:388 tests/dissect-sysfile.c:155
 msgid "Misplaced type 4 record."
 msgstr "Registre de tipus 4 fora de lloc."
 
-#: src/data/sys-file-reader.c:391
+#: src/data/sys-file-reader.c:392
 msgid "Duplicate type 6 (document) record."
 msgstr "Registre de tipus 6 (document) duplicat."
 
-#: src/data/sys-file-reader.c:400 src/data/sys-file-reader.c:900
+#: src/data/sys-file-reader.c:401 src/data/sys-file-reader.c:900
 #, c-format
 msgid "Unrecognized record type 7, subtype %d.  Please send a copy of this file, and the syntax which created it to %s."
 msgstr "Registre de tipus 7, subtipus %d no reconegut. Si us plau envieu una còpia d'aquest arxiu, així com de la sintaxi que el va crear a %s."
 
-#: src/data/sys-file-reader.c:409
+#: src/data/sys-file-reader.c:410
 #, c-format
 msgid "Record type 7, subtype %d found here has the same type as the record found near offset 0x%llx.  Please send a copy of this file, and the syntax which created it to %s."
 msgstr "Registre de tipus 7, subtipus %d que te el mateix tipus que el registre trobat prop de la posició 0x%llx. Si us plau envieu una còpia d'aquest arxiu, així com de la sintaxi que el va crear a %s."
 
-#: src/data/sys-file-reader.c:422 tests/dissect-sysfile.c:166
+#: src/data/sys-file-reader.c:423 tests/dissect-sysfile.c:166
 #, c-format
 msgid "Unrecognized record type %d."
 msgstr "Tipus de registre %d no reconegut."
@@ -714,8 +715,8 @@ msgstr "Variable de ponderació ha de ser numèrica (no la variable de text `%s'
 
 #: src/data/sys-file-reader.c:502
 #, c-format
-msgid "File header claims %d variable positions but %d were read from file."
-msgstr "Capçalera de l'arxiu requereix %d posicions de variable, però s'han llegit %d des de l'arxiu."
+msgid "File header claims %d variable positions but %zu were read from file."
+msgstr "Capçalera de l'arxiu requereix %d posicions de variable, però s'han llegit %zu des de l'arxiu."
 
 #: src/data/sys-file-reader.c:542
 #, c-format
@@ -754,8 +755,8 @@ msgstr "Registre d'índex de variable (tipus 4) no és seguit immediatament pel
 
 #: src/data/sys-file-reader.c:782
 #, c-format
-msgid "Number of variables associated with a value label (%d) is not between 1 and the number of variables (%zu)."
-msgstr "Nombre de variables associades amb una etiqueta de valors (%d) no està entre 1 i el nombre de variables (%zu)."
+msgid "Number of variables associated with a value label (%zu) is not between 1 and the number of variables (%zu)."
+msgstr "Nombre de variables associades amb una etiqueta de valors (%zu) no està entre 1 i el nombre de variables (%zu)."
 
 #: src/data/sys-file-reader.c:803
 #, c-format
@@ -827,321 +828,321 @@ msgstr "L'arxiu especifica un valor inesperat %g com a %s."
 
 #: src/data/sys-file-reader.c:1252
 #, c-format
-msgid "`%s' does not begin with `$' at UTF-8 offset %zu in MRSETS record."
-msgstr "`%s' not comença amb `$' a la posició UTF-8 %zu d'un registre MRSETS."
+msgid "`%s' does not begin with `$' at offset %zu in MRSETS record."
+msgstr "`%s' not comença amb `$' a la posició %zu d'un registre MRSETS."
 
 #: src/data/sys-file-reader.c:1263 src/data/sys-file-reader.c:1282
 #, c-format
-msgid "Missing space following `%c' at UTF-8 offset %zu in MRSETS record."
-msgstr "Espai perdut darrera `%c' a la posició UTF-8 %zu d'un registre MRSETS."
+msgid "Missing space following `%c' at offset %zu in MRSETS record."
+msgstr "Espai perdut darrera `%c' a la posició %zu al registre MRSETS."
 
 #: src/data/sys-file-reader.c:1292
 #, c-format
-msgid "Unexpected label source value `%s' following `E' at UTF-8 offset %zu in MRSETS record."
-msgstr "Valor d'etiqueta no esperat `%s' darrera `E' a la posició UTF-8 %zu d'un registre MRSETS."
+msgid "Unexpected label source value `%s' following `E' at offset %zu in MRSETS record."
+msgstr "Valor d'etiqueta no esperat `%s' darrera `E' a la posició %zu del registre MRSETS."
 
 #: src/data/sys-file-reader.c:1299
 #, c-format
-msgid "Missing `C', `D', or `E' at UTF-8 offset %zu in MRSETS record."
-msgstr "Manca `C', `D' o `E' a la posició UTF-8 %zu d'un registre MRSETS."
+msgid "Missing `C', `D', or `E' at offset %zu in MRSETS record."
+msgstr "Manca `C', `D' o `E' a la posició %zu d'un registre MRSETS."
 
-#: src/data/sys-file-reader.c:1329
+#: src/data/sys-file-reader.c:1331
 #, c-format
-msgid "Missing new-line parsing variable names at UTF-8 offset %zu in MRSETS record."
-msgstr "Manca nom de variables de nova línia en la posició UTF-8 %zu d'un registre MRSETS."
+msgid "Missing new-line parsing variable names at offset %zu in MRSETS record."
+msgstr "Manquen noms de variable de nova línia en la posició %zu d'un registre MRSETS."
 
-#: src/data/sys-file-reader.c:1341
+#: src/data/sys-file-reader.c:1347
 #, c-format
-msgid "Duplicate variable name %s at UTF-8 offset %zu in MRSETS record."
-msgstr "Nom de la variable %s duplicat a la posició UTF-8 %zu d'un registre MRSETS."
+msgid "Duplicate variable name %s at offset %zu in MRSETS record."
+msgstr "Nom de la variable %s duplicat a la posició %zu d'un registre MRSETS."
 
-#: src/data/sys-file-reader.c:1355
+#: src/data/sys-file-reader.c:1363
 #, c-format
 msgid "MRSET %s contains both string and numeric variables."
 msgstr "MRSET %s contè variables textuals i numeriques."
 
-#: src/data/sys-file-reader.c:1371
+#: src/data/sys-file-reader.c:1379
 #, c-format
 msgid "MRSET %s has only %zu variables."
 msgstr "MRSET %s nomès te %zu variables."
 
-#: src/data/sys-file-reader.c:1417 tests/dissect-sysfile.c:771
+#: src/data/sys-file-reader.c:1425 tests/dissect-sysfile.c:771
 #, c-format
 msgid "Extension 11 has bad count %zu (for %zu variables)."
 msgstr "Extensió 11 té un recompte invàlid %zu (per a %zu variables)."
 
-#: src/data/sys-file-reader.c:1451
+#: src/data/sys-file-reader.c:1459
 #, c-format
 msgid "Invalid variable display parameters for variable %zu (%s).  Default parameters substituted."
 msgstr "Paràmetres de visualització de variable no vàlids per a la variable %zu (%s). Substitució pels paràmetres per defecte."
 
-#: src/data/sys-file-reader.c:1548
+#: src/data/sys-file-reader.c:1556
 #, c-format
 msgid "Long variable mapping from %s to invalid variable name `%s'."
 msgstr "Identificació de variable llarga des de %s cap a un nom de variable invàlid  '%s'."
 
-#: src/data/sys-file-reader.c:1559
+#: src/data/sys-file-reader.c:1567
 #, c-format
 msgid "Duplicate long variable name `%s'."
 msgstr "Nom de la variable llarga `%s' duplicat."
 
-#: src/data/sys-file-reader.c:1592
+#: src/data/sys-file-reader.c:1600
 #, c-format
 msgid "%s listed as string of invalid length %s in very long string record."
 msgstr "%s figura com a cadena de longitud no vàlida %s a un registre de cadena molt llarg."
 
-#: src/data/sys-file-reader.c:1603
+#: src/data/sys-file-reader.c:1611
 #, c-format
 msgid "%s listed in very long string record with width %s, which requires only one segment."
 msgstr "%s figura en el registre de cadena molt llarga amb longitud %s, que requereix només un segment."
 
-#: src/data/sys-file-reader.c:1610
+#: src/data/sys-file-reader.c:1618
 #, c-format
 msgid "Very long string %s overflows dictionary."
 msgstr "Cadena molt llarga %s desborda el diccionari."
 
-#: src/data/sys-file-reader.c:1625
+#: src/data/sys-file-reader.c:1633
 #, c-format
 msgid "Very long string with width %ld has segment %d of width %d (expected %d)."
 msgstr "Cadena molt llarga amb una mida de %ld conté segment %d de longitud %d (s'espera %d)."
 
-#: src/data/sys-file-reader.c:1659
+#: src/data/sys-file-reader.c:1667
 #, c-format
 msgid "Variables associated with value label are not all of identical type.  Variable %s is %s, but variable %s is %s."
 msgstr "Les variables associades amb etiqueta de valors no són totes del mateix tipus.  La variable %s és %s, però la variable %s és %s."
 
-#: src/data/sys-file-reader.c:1676
+#: src/data/sys-file-reader.c:1684
 #, c-format
 msgid "Value labels may not be added to long string variables (e.g. %s) using records types 3 and 4."
 msgstr "No es pot afegir etiquetes dels valors a les variables de cadena llarga (e.g. %s) utilitzant els tipus de registres 3 i 4."
 
-#: src/data/sys-file-reader.c:1695
+#: src/data/sys-file-reader.c:1703
 #, c-format
 msgid "Duplicate value label for %g on %s."
 msgstr "Etiqueta de valors duplicats per %g en %s."
 
-#: src/data/sys-file-reader.c:1699 src/data/sys-file-reader.c:1941
+#: src/data/sys-file-reader.c:1707 src/data/sys-file-reader.c:1949
 #, c-format
 msgid "Duplicate value label for `%.*s' on %s."
 msgstr "Etiqueta de valor duplicat per a `%.*s' a %s."
 
-#: src/data/sys-file-reader.c:1724
+#: src/data/sys-file-reader.c:1732
 #, c-format
-msgid "Variable index %d not in valid range 1...%d."
-msgstr "Índex de la variable %d no en l'interval vàlid de 1...%d."
+msgid "Variable index %d not in valid range 1...%zu."
+msgstr "Índex de la variable %d fora de l'interval vàlid de 1...%zu."
 
-#: src/data/sys-file-reader.c:1733
+#: src/data/sys-file-reader.c:1741
 #, c-format
 msgid "Variable index %d refers to long string continuation."
 msgstr "Índex de la variable %d es refereix a una continuació de cadena llarga."
 
-#: src/data/sys-file-reader.c:1769
+#: src/data/sys-file-reader.c:1777
 #, c-format
 msgid "Error parsing attribute value %s[%d]."
 msgstr "Error en analitzar el valor de l'atribut %s[%d]."
 
-#: src/data/sys-file-reader.c:1783
+#: src/data/sys-file-reader.c:1791
 #, c-format
 msgid "Attribute value %s[%d] is not quoted: %s."
 msgstr "El valor de l'atribut %s[%d] no esta entre cometes: %s."
 
-#: src/data/sys-file-reader.c:1836
+#: src/data/sys-file-reader.c:1844
 msgid "Long string value label record ends unexpectedly."
 msgstr "Etiqueta de valor d'un registre de text molt llarg finalitza inesperadament."
 
-#: src/data/sys-file-reader.c:1875
+#: src/data/sys-file-reader.c:1883
 #, c-format
 msgid "Ignoring long string value record for unknown variable %s."
 msgstr "Ignorant el registre del valor de cadena llarga per a la variable desconeguda %s."
 
-#: src/data/sys-file-reader.c:1880
+#: src/data/sys-file-reader.c:1888
 #, c-format
 msgid "Ignoring long string value record for numeric variable %s."
 msgstr "Ignorant el registre del valor de cadena llarga per a la variable numèrica %s."
 
-#: src/data/sys-file-reader.c:1887
+#: src/data/sys-file-reader.c:1895
 #, c-format
 msgid "Ignoring long string value record for variable %s because the record's width (%d) does not match the variable's width (%d)."
 msgstr "Ignorant el registre del valor de cadena llarga %s ja que la mida del registre (%d) no coincideix amb la mida de la variable (%d)."
 
-#: src/data/sys-file-reader.c:1916
+#: src/data/sys-file-reader.c:1924
 #, c-format
 msgid "Ignoring long string value %zu for variable %s, with width %d, that has bad value width %zu."
 msgstr "Ignorant el valor de cadena llarga %zu per a la variable %s, d'amplada %d, que té una amplada de valor incorrecta %zu."
 
-#: src/data/sys-file-reader.c:2020
+#: src/data/sys-file-reader.c:2028
 msgid "File ends in partial case."
 msgstr "L'arxiu acaba en un cas parcial."
 
-#: src/data/sys-file-reader.c:2028
+#: src/data/sys-file-reader.c:2036
 #, c-format
 msgid "Error reading case from file %s."
 msgstr "Error llegint un cas de l'arxiu %s."
 
-#: src/data/sys-file-reader.c:2130
+#: src/data/sys-file-reader.c:2138
 msgid "Possible compressed data corruption: compressed spaces appear in numeric field."
 msgstr "Possible corrupció de dades comprimides: apareixen espais comprimits a un camp numeric."
 
-#: src/data/sys-file-reader.c:2184
+#: src/data/sys-file-reader.c:2192
 #, c-format
 msgid "Possible compressed data corruption: string contains compressed integer (opcode %d)."
 msgstr "Possible corrupció de dades comprimides: una cadena textual contè un enter comprimit (opcode %d)."
 
-#: src/data/sys-file-reader.c:2273
+#: src/data/sys-file-reader.c:2286
 #, c-format
 msgid "Suppressed %d additional related warnings."
 msgstr "Suprimides %d advertències addicionals."
 
-#: src/data/sys-file-reader.c:2318 src/data/sys-file-reader.c:2335
+#: src/data/sys-file-reader.c:2332 src/data/sys-file-reader.c:2349
 #, c-format
 msgid "Dictionary record refers to unknown variable %s."
 msgstr "El registre diccionari es refereix a la variable desconeguda %s."
 
-#: src/data/sys-file-reader.c:2397
+#: src/data/sys-file-reader.c:2411
 #, c-format
-msgid "Expecting digit at UTF-8 offset %zu in MRSETS record."
-msgstr "S'espera un dígit a la posició UTF-8 %zu d'un registre MRSETS."
+msgid "Expecting digit at offset %zu in MRSETS record."
+msgstr "S'espera un dígit a la posició %zu d'un registre MRSETS."
 
-#: src/data/sys-file-reader.c:2405
+#: src/data/sys-file-reader.c:2419
 #, c-format
-msgid "Expecting space at UTF-8 offset %zu in MRSETS record."
-msgstr "S'espera un espai a la posició UTF-8 %zu d'un registre MRSETS."
+msgid "Expecting space at offset %zu in MRSETS record."
+msgstr "S'espera un espai a la posició %zu d'un registre MRSETS."
 
-#: src/data/sys-file-reader.c:2413
+#: src/data/sys-file-reader.c:2427
 #, c-format
-msgid "%zu-byte string starting at UTF-8 offset %zu exceeds record length %zu."
-msgstr "El text de %zu-bytes que comença en la posició UTF-8 %zu excedeix la mida del registre %zu."
+msgid "%zu-byte string starting at offset %zu exceeds record length %zu."
+msgstr "El text de %zu-bytes que comença en la posició %zu excedeix la mida del registre %zu."
 
-#: src/data/sys-file-reader.c:2423
+#: src/data/sys-file-reader.c:2437
 #, c-format
-msgid "Expecting space at UTF-8 offset %zu following %zu-byte string."
-msgstr "S'espera un espai en la posició UTF-8 %zu darrera d'un text de %zu-bytes."
+msgid "Expecting space at offset %zu following %zu-byte string."
+msgstr "S'espera un espai en la posició %zu darrera d'un text de %zu-bytes."
 
-#: src/data/sys-file-reader.c:2465
+#: src/data/sys-file-reader.c:2478
 #, c-format
 msgid "`%s' near offset 0x%llx: "
 msgstr "`%s' prop de la posició 0x%llx: "
 
-#: src/data/sys-file-reader.c:2468
+#: src/data/sys-file-reader.c:2481
 #, c-format
 msgid "`%s': "
 msgstr "`%s': "
 
-#: src/data/sys-file-reader.c:2525 tests/dissect-sysfile.c:1356
+#: src/data/sys-file-reader.c:2538 tests/dissect-sysfile.c:1356
 #, c-format
 msgid "System error: %s."
 msgstr "Error de sistema: %s."
 
-#: src/data/sys-file-reader.c:2527 tests/dissect-sysfile.c:1358
+#: src/data/sys-file-reader.c:2540 tests/dissect-sysfile.c:1358
 msgid "Unexpected end of file."
 msgstr "Final d'arxiu inesperat."
 
-#: src/data/sys-file-writer.c:180
+#: src/data/sys-file-writer.c:186
 #, c-format
 msgid "Unknown system file version %d. Treating as version %d."
 msgstr "Versió d'arxiu de sistema %d desconeguda. Es tractarà com a versió %d."
 
-#: src/data/sys-file-writer.c:997
+#: src/data/sys-file-writer.c:1015
 #, c-format
 msgid "An I/O error occurred writing system file `%s'."
 msgstr "S'ha produït un error de E/S en desar l'arxiu de sistema `%s'."
 
-#: src/data/variable.c:599
+#: src/data/variable.c:601
 #, c-format
 msgid "Truncating variable label for variable `%s' to %d bytes."
 msgstr "Truncant la etiqueta de variable `%s' a %d caràcters."
 
-#: src/language/command.c:193 src/language/expressions/parse.c:1294
+#: src/language/command.c:196 src/language/expressions/parse.c:1294
 #: src/language/utilities/set.q:196
 #, c-format
 msgid "%s is not yet implemented."
 msgstr "%s encara no està implementat."
 
-#: src/language/command.c:198
+#: src/language/command.c:201
 #, c-format
 msgid "%s may be used only in testing mode."
 msgstr "%s només pot ser utilitzat en el mode de prova."
 
-#: src/language/command.c:203
+#: src/language/command.c:206
 #, c-format
 msgid "%s may be used only in enhanced syntax mode."
 msgstr "%s només pot ser utilitzat en el mode de sintaxi ampliat."
 
-#: src/language/command.c:331
+#: src/language/command.c:334
 msgid "expecting command name"
 msgstr "esperant nom de comando"
 
-#: src/language/command.c:333
+#: src/language/command.c:336
 #, c-format
 msgid "Unknown command `%s'."
 msgstr "Comando `%s' desconegut."
 
-#: src/language/command.c:366
+#: src/language/command.c:369
 #, c-format
 msgid "%s is allowed only before the active dataset has been defined."
 msgstr "%s només es permet abans que l'arxiu de dades actiu s'ha definit."
 
-#: src/language/command.c:370
+#: src/language/command.c:373
 #, c-format
 msgid "%s is allowed only after the active dataset has been defined."
 msgstr "%s només es permet després que l'arxiu de dades actiu s'ha definit."
 
-#: src/language/command.c:374
+#: src/language/command.c:377
 #, c-format
 msgid "%s is allowed only inside INPUT PROGRAM."
 msgstr "%s només es permet dins de INPUT PROGRAM."
 
-#: src/language/command.c:378
+#: src/language/command.c:381
 #, c-format
 msgid "%s is allowed only inside FILE TYPE."
 msgstr "%s només es permet dins de FILE TYPE."
 
-#: src/language/command.c:385
+#: src/language/command.c:388
 #, c-format
 msgid "%s is allowed only before the active dataset has been defined or inside INPUT PROGRAM."
 msgstr "%s només es permet abans que l'arxiu de dades actiu s'ha definit o dins de INPUT PROGRAM."
 
-#: src/language/command.c:389
+#: src/language/command.c:392
 #, c-format
 msgid "%s is allowed only before the active dataset has been defined or inside FILE TYPE."
 msgstr "%s només es permet abans que l'arxiu de dades actiu s'ha definit o dins de FILE TYPE."
 
-#: src/language/command.c:393
+#: src/language/command.c:396
 #, c-format
 msgid "%s is allowed only after the active dataset has been defined or inside INPUT PROGRAM."
 msgstr "%s només es permet després que l'arxiu de dades actiu s'ha definit, o dins de INPUT PROGRAM."
 
-#: src/language/command.c:397
+#: src/language/command.c:400
 #, c-format
 msgid "%s is allowed only after the active dataset has been defined or inside FILE TYPE."
 msgstr "%s només es permet després que l'arxiu de dades actiu s'ha definit, o dins de FILE TYPE."
 
-#: src/language/command.c:401
+#: src/language/command.c:404
 #, c-format
 msgid "%s is allowed only inside INPUT PROGRAM or inside FILE TYPE."
 msgstr "%s només es permet dins de INPUT PROGRAM o FILE TYPE."
 
-#: src/language/command.c:407
+#: src/language/command.c:410
 #, c-format
 msgid "%s is allowed only after the active dataset has been defined, inside INPUT PROGRAM, or inside FILE TYPE."
 msgstr "%s només es permet després que l'arxiu de dades actiu s'ha definit, dins de INPUT PROGRAM, o FILE TYPE."
 
-#: src/language/command.c:412
+#: src/language/command.c:415
 #, c-format
 msgid "%s is allowed only before the active dataset has been defined, inside INPUT PROGRAM, or inside FILE TYPE."
 msgstr "%s només es permet abans que l'arxiu de dades actiu s'ha definit, dins de INPUT PROGRAM, o FILE TYPE."
 
-#: src/language/command.c:430 src/language/command.c:433
+#: src/language/command.c:433 src/language/command.c:436
 #, c-format
 msgid "%s is not allowed inside %s."
 msgstr "%s no és permes dins de %s."
 
-#: src/language/command.c:515 src/language/utilities/host.c:130
+#: src/language/command.c:518 src/language/utilities/host.c:130
 #: src/language/utilities/permissions.c:104
 msgid "This command not allowed when the SAFER option is set."
 msgstr "Aquesta ordre no està permesa quan l'opció SAFER està activa."
 
-#: src/language/command.c:531
+#: src/language/command.c:534
 #, c-format
 msgid "Error removing `%s': %s."
 msgstr "Error d'eliminació de '%s' : %s."
@@ -1200,55 +1201,55 @@ msgstr "Error de sintaxi a `%s'"
 msgid "Syntax error"
 msgstr "Error de sintaxi"
 
-#: src/language/lexer/lexer.c:1358
+#: src/language/lexer/lexer.c:1363
 #, c-format
 msgid "String of hex digits has %d characters, which is not a multiple of 2"
 msgstr "La cadena de dígits hexadecimals té %d caràcters, que no és un múltiple de 2."
 
-#: src/language/lexer/lexer.c:1365
+#: src/language/lexer/lexer.c:1370
 #, c-format
 msgid "`%c' is not a valid hex digit"
 msgstr "'%c' no és un dígit hexadecimal vàlid."
 
-#: src/language/lexer/lexer.c:1370
+#: src/language/lexer/lexer.c:1375
 #, c-format
 msgid "Unicode string contains %d bytes, which is not in the valid range of 1 to 8 bytes"
 msgstr "Cadena Unicode conté %d bytes, que está fora del rang vàlid entre 1 y 8 bytes"
 
-#: src/language/lexer/lexer.c:1376
+#: src/language/lexer/lexer.c:1381
 #, c-format
 msgid "U+%04X is not a valid Unicode code point"
 msgstr "U+%04X no és un punt de codi Unicode vàlid"
 
-#: src/language/lexer/lexer.c:1381
+#: src/language/lexer/lexer.c:1386
 msgid "Unterminated string constant"
 msgstr "Constante de cadena inacabada"
 
-#: src/language/lexer/lexer.c:1385
+#: src/language/lexer/lexer.c:1390
 #, c-format
 msgid "Missing exponent following `%s'"
 msgstr "Manca l'exponent a continuació de `%s'"
 
-#: src/language/lexer/lexer.c:1390
+#: src/language/lexer/lexer.c:1395
 msgid "Unexpected `.' in middle of command"
 msgstr "`.' inesperat al mig d'un comand"
 
-#: src/language/lexer/lexer.c:1396
+#: src/language/lexer/lexer.c:1401
 #, c-format
 msgid "Bad character %s in input"
 msgstr "Caràcter erroni `%s' a l'entrada"
 
-#: src/language/lexer/lexer.c:1490
+#: src/language/lexer/lexer.c:1495
 #, c-format
 msgid "Opening `%s': %s."
 msgstr "Obrint `%s': %s."
 
-#: src/language/lexer/lexer.c:1520
+#: src/language/lexer/lexer.c:1525
 #, c-format
 msgid "Error reading `%s': %s."
 msgstr "Error leyendo `%s': %s."
 
-#: src/language/lexer/lexer.c:1534
+#: src/language/lexer/lexer.c:1539
 #, c-format
 msgid "Error closing `%s': %s."
 msgstr "Error tancant '%s' : %s."
@@ -1473,8 +1474,8 @@ msgstr "El nom de la variable fictícia `%s' es dóna dues vegades."
 
 #: src/language/control/repeat.c:162
 #, c-format
-msgid "Dummy variable `%s' had %d substitutions, so `%s' must also, but %d were specified."
-msgstr "La variable fictícia `%.s' té %d substitucions, així que `%.s' també n'hauria de tenir-les, però es van especificar %d."
+msgid "Dummy variable `%s' had %zu substitutions, so `%s' must also, but %zu were specified."
+msgstr "La variable fictícia `%.s' té %zu substitucions, així que `%s' també n'hauria de tenir-les, però es van especificar %zu."
 
 #: src/language/control/repeat.c:366
 msgid "Ranges may only have integer bounds."
@@ -1519,7 +1520,7 @@ msgstr "esperant %s o %s"
 msgid "Variable %s is %s in target file, but %s in source file."
 msgstr "La variable %s és %s en l'arxiu de destinació, però %s en l'arxiu d'origen."
 
-#: src/language/dictionary/apply-dictionary.c:111
+#: src/language/dictionary/apply-dictionary.c:110
 msgid "No matching variables found between the source and target files."
 msgstr "No s'han trobat coincidències de variables entre els arxius d'origen i de destinació."
 
@@ -1531,11 +1532,11 @@ msgstr "DELETE VARIABLES no pot ser utilitzat després de TEMPORARY. Les transfo
 msgid "DELETE VARIABLES may not be used to delete all variables from the active dataset dictionary.  Use NEW FILE instead."
 msgstr "DELETE VARIABLES no pot ser utilitzar per esborrar totes les variables de l'arxiu de dades de diccionari actiu. Utilitzeu NEW FILE en el seu lloc."
 
-#: src/language/dictionary/formats.c:90
+#: src/language/dictionary/formats.c:87
 msgid "`(' expected after variable list."
 msgstr "`(' esperat després de la llista de variables."
 
-#: src/language/dictionary/formats.c:100 src/language/dictionary/numeric.c:75
+#: src/language/dictionary/formats.c:97 src/language/dictionary/numeric.c:75
 msgid "`)' expected after output format."
 msgstr "`)' esperat després del format de resultats."
 
@@ -1705,8 +1706,8 @@ msgstr "Conjunt de Categories Múltiples"
 
 #: src/language/dictionary/mrsets.c:570
 #: src/language/dictionary/split-file.c:84
-#: src/language/dictionary/sys-file-info.c:338
-#: src/language/dictionary/sys-file-info.c:577
+#: src/language/dictionary/sys-file-info.c:336
+#: src/language/dictionary/sys-file-info.c:575
 #: src/ui/gui/psppire-var-sheet.c:538 src/ui/gui/psppire-var-store.c:837
 #: src/ui/gui/compute.ui:467 src/ui/gui/crosstabs.ui:292
 msgid "Label"
@@ -1728,15 +1729,15 @@ msgstr "Proporcionat per l'usuari"
 msgid "Counted value"
 msgstr "Valor de recompte"
 
-#: src/language/dictionary/mrsets.c:584
+#: src/language/dictionary/mrsets.c:590
 msgid "Category label source"
 msgstr "Font d'etiquetes de categoria"
 
-#: src/language/dictionary/mrsets.c:586
+#: src/language/dictionary/mrsets.c:592
 msgid "Variable labels"
 msgstr "Etiquetes de variable"
 
-#: src/language/dictionary/mrsets.c:587
+#: src/language/dictionary/mrsets.c:593
 msgid "Value labels of counted value"
 msgstr "Etiquetes de valor del valor de recompte"
 
@@ -1777,13 +1778,13 @@ msgid "Renaming would duplicate variable name %s."
 msgstr "Canviar el nom duplicaria el nom de la variable %s."
 
 #: src/language/dictionary/split-file.c:83
-#: src/language/dictionary/sys-file-info.c:423
-#: src/language/dictionary/sys-file-info.c:576
+#: src/language/dictionary/sys-file-info.c:421
+#: src/language/dictionary/sys-file-info.c:574
 #: src/language/stats/cochran.c:170 src/language/stats/reliability.c:753
 #: src/language/stats/reliability.c:764 src/language/stats/crosstabs.q:1234
 #: src/language/stats/crosstabs.q:1261 src/language/stats/crosstabs.q:1284
 #: src/language/stats/crosstabs.q:1309 src/language/stats/examine.q:1840
-#: src/language/stats/frequencies.q:823
+#: src/language/stats/frequencies.q:821
 msgid "Value"
 msgstr "Valor"
 
@@ -1861,7 +1862,7 @@ msgid "Type:"
 msgstr "Tipus:"
 
 #: src/language/dictionary/sys-file-info.c:127
-#: src/ui/gui/psppire-data-window.c:621
+#: src/ui/gui/psppire-data-window.c:509
 msgid "System File"
 msgstr "Arxiu de Sistema"
 
@@ -1895,13 +1896,13 @@ msgid "Charset:"
 msgstr "Conjunt de caràcters:"
 
 #: src/language/dictionary/sys-file-info.c:150
-#: src/language/dictionary/sys-file-info.c:338
+#: src/language/dictionary/sys-file-info.c:336
 msgid "Description"
 msgstr "Descripció"
 
 #: src/language/dictionary/sys-file-info.c:151
-#: src/language/dictionary/sys-file-info.c:340
-#: src/language/dictionary/sys-file-info.c:657
+#: src/language/dictionary/sys-file-info.c:338
+#: src/language/dictionary/sys-file-info.c:645
 msgid "Position"
 msgstr "Posició"
 
@@ -1909,103 +1910,104 @@ msgstr "Posició"
 msgid "The active dataset does not have a file label."
 msgstr "L'arxiu de dades actiu no té etiqueta d'arxiu."
 
-#: src/language/dictionary/sys-file-info.c:201
-msgid "File label:"
-msgstr "Etiqueta d'arxiu:"
+#: src/language/dictionary/sys-file-info.c:200
+#, c-format
+msgid "File label: %s"
+msgstr "Etiqueta d'arxiu: %s"
 
-#: src/language/dictionary/sys-file-info.c:276
+#: src/language/dictionary/sys-file-info.c:274
 msgid "No variables to display."
 msgstr "Cap variable per mostrar."
 
-#: src/language/dictionary/sys-file-info.c:290
+#: src/language/dictionary/sys-file-info.c:288
 msgid "Macros not supported."
 msgstr "Macros no disponibles."
 
-#: src/language/dictionary/sys-file-info.c:299
+#: src/language/dictionary/sys-file-info.c:297
 msgid "The active dataset dictionary does not contain any documents."
 msgstr "El diccionari de l'arxiu de dades actiu no conté cap document. "
 
-#: src/language/dictionary/sys-file-info.c:306
+#: src/language/dictionary/sys-file-info.c:304
 msgid "Documents in the active dataset:"
 msgstr "Documents a l'arxiu de dades actiu:"
 
-#: src/language/dictionary/sys-file-info.c:422
+#: src/language/dictionary/sys-file-info.c:420
 msgid "Attribute"
 msgstr "Atribut"
 
-#: src/language/dictionary/sys-file-info.c:478
+#: src/language/dictionary/sys-file-info.c:476
 #, c-format
 msgid "Format: %s"
 msgstr "Format: %s"
 
-#: src/language/dictionary/sys-file-info.c:485
+#: src/language/dictionary/sys-file-info.c:483
 #, c-format
 msgid "Print Format: %s"
 msgstr "Format d'Impressió: %s"
 
-#: src/language/dictionary/sys-file-info.c:489
+#: src/language/dictionary/sys-file-info.c:487
 #, c-format
 msgid "Write Format: %s"
 msgstr "Format d'Escriptura: %s"
 
-#: src/language/dictionary/sys-file-info.c:502
+#: src/language/dictionary/sys-file-info.c:500
 #, c-format
 msgid "Measure: %s"
 msgstr "Mesura: %s"
 
-#: src/language/dictionary/sys-file-info.c:503
+#: src/language/dictionary/sys-file-info.c:501
 #: src/ui/gui/psppire-var-sheet.c:111
 msgid "Nominal"
 msgstr "Nominal"
 
-#: src/language/dictionary/sys-file-info.c:504
+#: src/language/dictionary/sys-file-info.c:502
 #: src/ui/gui/psppire-var-sheet.c:112
 msgid "Ordinal"
 msgstr "Ordinal"
 
-#: src/language/dictionary/sys-file-info.c:505
+#: src/language/dictionary/sys-file-info.c:503
 #: src/ui/gui/psppire-var-sheet.c:113
 msgid "Scale"
 msgstr "Escala"
 
-#: src/language/dictionary/sys-file-info.c:508
+#: src/language/dictionary/sys-file-info.c:506
 #, c-format
 msgid "Display Alignment: %s"
 msgstr "Alineació de la mostra: %s"
 
-#: src/language/dictionary/sys-file-info.c:509
+#: src/language/dictionary/sys-file-info.c:507
 #: src/ui/gui/psppire-var-sheet.c:104
 msgid "Left"
 msgstr "Esquerra"
 
-#: src/language/dictionary/sys-file-info.c:510
+#: src/language/dictionary/sys-file-info.c:508
 #: src/ui/gui/psppire-var-sheet.c:106
 msgid "Center"
 msgstr "Centre"
 
-#: src/language/dictionary/sys-file-info.c:511
+#: src/language/dictionary/sys-file-info.c:509
 #: src/ui/gui/psppire-var-sheet.c:105
 msgid "Right"
 msgstr "Dreta"
 
-#: src/language/dictionary/sys-file-info.c:514
+#: src/language/dictionary/sys-file-info.c:512
 #, c-format
 msgid "Display Width: %d"
 msgstr "Amplada de la mostra: %d"
 
-#: src/language/dictionary/sys-file-info.c:528
+#: src/language/dictionary/sys-file-info.c:526
 msgid "Missing Values: "
 msgstr "Valors perduts:"
 
-#: src/language/dictionary/sys-file-info.c:637
+#: src/language/dictionary/sys-file-info.c:625
 msgid "No vectors defined."
 msgstr "Vectors no definits."
 
-#: src/language/dictionary/sys-file-info.c:656
+#: src/language/dictionary/sys-file-info.c:644
 msgid "Vector"
 msgstr "Vector"
 
-#: src/language/dictionary/sys-file-info.c:659
+#: src/language/dictionary/sys-file-info.c:647
 msgid "Print Format"
 msgstr "Format d'Impressió"
 
@@ -2089,21 +2091,21 @@ msgstr "Error d'execució del comandament: %s."
 msgid "   (Entered %s)"
 msgstr "   (Introduït %s)"
 
-#: src/language/utilities/include.c:64
+#: src/language/utilities/include.c:65
 msgid "expecting file name"
 msgstr "esperant nom d'arxiu"
 
-#: src/language/utilities/include.c:74
+#: src/language/utilities/include.c:75
 #, c-format
 msgid "Can't find `%s' in include file search path."
 msgstr "No es pot trobar `%s' en la ruta de cerca de l'arxiu d'inclusió."
 
-#: src/language/utilities/include.c:107
+#: src/language/utilities/include.c:109
 #, c-format
 msgid "expecting %s, %s, or %s after %s"
 msgstr "s'espera %s, %s o %s darrera %s"
 
-#: src/language/utilities/include.c:125 src/language/utilities/include.c:143
+#: src/language/utilities/include.c:127 src/language/utilities/include.c:145
 #, c-format
 msgid "expecting %s or %s after %s"
 msgstr "s'espera %s o %s darrera %s"
@@ -2282,7 +2284,7 @@ msgstr "Grup 2"
 #: src/language/stats/sign.c:95 src/language/stats/wilcoxon.c:255
 #: src/ui/gui/crosstabs-dialog.c:59 src/language/stats/crosstabs.q:832
 #: src/language/stats/crosstabs.q:1176 src/language/stats/crosstabs.q:1560
-#: src/language/stats/examine.q:1104 src/language/stats/frequencies.q:881
+#: src/language/stats/examine.q:1104 src/language/stats/frequencies.q:879
 #: src/language/stats/regression.q:293
 msgid "Total"
 msgstr "Total"
@@ -2299,7 +2301,7 @@ msgstr "Categoria"
 #: src/language/stats/oneway.c:686 src/language/stats/reliability.c:536
 #: src/language/stats/sign.c:74 src/language/stats/wilcoxon.c:238
 #: src/language/stats/crosstabs.q:839 src/language/stats/examine.q:1175
-#: src/language/stats/frequencies.q:1043 src/language/stats/t-test.q:509
+#: src/language/stats/frequencies.q:1041 src/language/stats/t-test.q:509
 #: src/language/stats/t-test.q:529 src/language/stats/t-test.q:629
 #: src/language/stats/t-test.q:1105
 msgid "N"
@@ -2527,7 +2529,7 @@ msgstr "Font"
 msgid "Target"
 msgstr "Destí"
 
-#: src/language/stats/descriptives.c:683
+#: src/language/stats/descriptives.c:684
 #, c-format
 msgid "Z-score of %s"
 msgstr "puntuació-Z de %s"
@@ -2577,10 +2579,9 @@ msgstr "Component"
 msgid "Factor"
 msgstr "Factor"
 
-#: src/language/stats/factor.c:1345 src/language/stats/factor.c:1493
-#: src/ui/gui/psppire-data-store.c:755 src/ui/gui/psppire-var-store.c:700
-#: src/ui/gui/psppire-var-store.c:710 src/ui/gui/psppire-var-store.c:720
-#: src/ui/gui/psppire-var-store.c:826
+#: src/language/stats/factor.c:1345 src/ui/gui/psppire-data-store.c:755
+#: src/ui/gui/psppire-var-store.c:699 src/ui/gui/psppire-var-store.c:709
+#: src/ui/gui/psppire-var-store.c:719 src/ui/gui/psppire-var-store.c:826
 #, c-format
 msgid "%d"
 msgstr "%d"
@@ -2610,6 +2611,11 @@ msgstr "% de Variància"
 msgid "Cumulative %"
 msgstr "% Acumulat"
 
+#: src/language/stats/factor.c:1493
+#, c-format
+msgid "%zu"
+msgstr "%zu"
+
 #: src/language/stats/factor.c:1576
 msgid "Correlation Matrix"
 msgstr "Matriu de Correlació"
@@ -2775,7 +2781,7 @@ msgid "PAIRED was specified but the number of variables preceding WITH (%zu) did
 msgstr "S'ha especificat PAIRED però el nombre de variables abans de WITH (%zu) not conicideixen amb en nombre de variables seguents (%zu)."
 
 #: src/language/stats/npar-summary.c:142 src/language/stats/examine.q:1995
-#: src/language/stats/examine.q:2012 src/language/stats/frequencies.q:1059
+#: src/language/stats/examine.q:2012 src/language/stats/frequencies.q:1057
 #: src/ui/gui/examine.ui:345
 msgid "Percentiles"
 msgstr "Percentils"
@@ -2903,6 +2909,37 @@ msgstr "S'assumeix igualtat de variances"
 msgid "Does not assume equal"
 msgstr "No s'assumeix igualtat"
 
+#: src/language/stats/quick-cluster.c:369
+msgid "Number of clusters may not be larger than the number of cases."
+msgstr "El nombre d'agrupament no pot ser més gran que el nombre de cassos."
+
+#: src/language/stats/quick-cluster.c:411
+msgid "Final Cluster Centers"
+msgstr "Centres d'Agrupaments Finals"
+
+#: src/language/stats/quick-cluster.c:415
+msgid "Initial Cluster Centers"
+msgstr "Centres d'Agrupaments Inicials"
+
+#: src/language/stats/quick-cluster.c:418
+#: src/language/stats/quick-cluster.c:472
+msgid "Cluster"
+msgstr "Agrupament"
+
+#: src/language/stats/quick-cluster.c:470
+msgid "Number of Cases in each Cluster"
+msgstr "Nombre de cassos a cada Agrupament"
+
+#: src/language/stats/quick-cluster.c:484 src/language/stats/reliability.c:527
+#: src/language/stats/crosstabs.q:830 src/language/stats/examine.q:1102
+#: src/language/stats/frequencies.q:1042
+msgid "Valid"
+msgstr "Vàlid"
+
+#: src/language/stats/quick-cluster.c:515
+msgid "Variables cannot be parsed"
+msgstr "No es poden generar les variables"
+
 #: src/language/stats/reliability.c:141
 msgid "Reliability on a single variable is not useful."
 msgstr "L'anàlisi de fiabilitat d'una única variable és inútil."
@@ -2916,11 +2953,6 @@ msgstr "Resum de processament del Casos"
 msgid "Cases"
 msgstr "Casos"
 
-#: src/language/stats/reliability.c:527 src/language/stats/crosstabs.q:830
-#: src/language/stats/examine.q:1102 src/language/stats/frequencies.q:1044
-msgid "Valid"
-msgstr "Vàlid"
-
 #: src/language/stats/reliability.c:530
 msgid "Excluded"
 msgstr "Exclós"
@@ -3151,118 +3183,118 @@ msgstr "Rangs Negatius"
 msgid "Positive Ranks"
 msgstr "Rangs Positius"
 
-#: src/language/data-io/combine-files.c:211
+#: src/language/data-io/combine-files.c:212
 msgid "Cannot specify the active dataset since none has been defined."
 msgstr "No es pot especificar l'arxiu de dades actiu ja que cap no ha estat definit."
 
-#: src/language/data-io/combine-files.c:217
+#: src/language/data-io/combine-files.c:218
 msgid "This command may not be used after TEMPORARY when the active dataset is an input source.  Temporary transformations will be made permanent."
 msgstr "Aquest comando no pot ser utilitzat després de TEMPORARY quan l'arxiu de dades actiu és una font d'entrada.  Les transformacions temporals seran permanents."
 
-#: src/language/data-io/combine-files.c:251
+#: src/language/data-io/combine-files.c:252
 msgid "Multiple IN subcommands for a single FILE or TABLE."
 msgstr "Múltiples subcomandos IN  per a un únic FILE o TABLE."
 
-#: src/language/data-io/combine-files.c:303
+#: src/language/data-io/combine-files.c:304
 #, c-format
 msgid "File %s lacks BY variable %s."
 msgstr "L'arxiu %s no té variable BY %s."
 
-#: src/language/data-io/combine-files.c:306
+#: src/language/data-io/combine-files.c:307
 #, c-format
 msgid "Active dataset lacks BY variable %s."
 msgstr "Arxiu de dades actiu no té BY variable %s."
 
-#: src/language/data-io/combine-files.c:378
+#: src/language/data-io/combine-files.c:379
 msgid "The BY subcommand is required."
 msgstr "Es necessita el subcomando BY."
 
-#: src/language/data-io/combine-files.c:383
-#: src/language/data-io/combine-files.c:388
+#: src/language/data-io/combine-files.c:384
+#: src/language/data-io/combine-files.c:389
 #, c-format
 msgid "BY is required when %s is specified."
 msgstr "BY és necessari quan s'especifica %s."
 
-#: src/language/data-io/combine-files.c:521
+#: src/language/data-io/combine-files.c:514
 msgid "Combining files with incompatible encodings. String data may not be represented correctly."
 msgstr "Combinant arxius amb codificacions incompatibles. Les dades de la cadena no podran estar representades correctament."
 
-#: src/language/data-io/combine-files.c:563
+#: src/language/data-io/combine-files.c:555
 #, c-format
 msgid "Variable %s in file %s has different type or width from the same variable in earlier file."
 msgstr "La variable %s a l'arxiu %s és de tipus o amplada diferent respecte de la mateixa variable en l'arxiu anterior. "
 
-#: src/language/data-io/combine-files.c:569
+#: src/language/data-io/combine-files.c:561
 #, c-format
 msgid "In file %s, %s is numeric."
 msgstr "A l'arxiu %s, %s és numèric."
 
-#: src/language/data-io/combine-files.c:572
+#: src/language/data-io/combine-files.c:564
 #, c-format
 msgid "In file %s, %s is a string variable with width %d."
 msgstr "A l'arxiu %s, %s és una variable de cadena amb una amplada de %d."
 
-#: src/language/data-io/combine-files.c:577
+#: src/language/data-io/combine-files.c:569
 #, c-format
 msgid "In an earlier file, %s was numeric."
 msgstr "En un arxiu anterior, %s era numèric."
 
-#: src/language/data-io/combine-files.c:580
+#: src/language/data-io/combine-files.c:572
 #, c-format
 msgid "In an earlier file, %s was a string variable with width %d."
 msgstr "En un arxiu anterior, %s era una variable cadena amb una amplada de %d."
 
-#: src/language/data-io/combine-files.c:620
+#: src/language/data-io/combine-files.c:612
 #, c-format
 msgid "Variable name %s specified on %s subcommand duplicates an existing variable name."
 msgstr "Nom de la variable %s especificat al subcomando %s duplica el nom de la variable existent."
 
-#: src/language/data-io/combine-files.c:782
+#: src/language/data-io/combine-files.c:774
 #, c-format
 msgid "Encountered %zu sets of duplicate cases in the master file."
 msgstr "Trobats %zu conjunts de casos duplicats a l'arxiu principal."
 
-#: src/language/data-io/data-list.c:137
+#: src/language/data-io/data-list.c:140
 msgid "The END subcommand may only be used within INPUT PROGRAM."
 msgstr "El subcomando END només pot ser utilitzat dins de INPUT PROGRAM."
 
-#: src/language/data-io/data-list.c:143
+#: src/language/data-io/data-list.c:146
 msgid "The END subcommand may only be specified once."
 msgstr "El subcomando END només pot ser especificat una vegada."
 
-#: src/language/data-io/data-list.c:181
+#: src/language/data-io/data-list.c:184
 msgid "Only one of FIXED, FREE, or LIST may be specified."
 msgstr "Només un de FIXED, FREE, o LIST pot ser especificat."
 
-#: src/language/data-io/data-list.c:244
+#: src/language/data-io/data-list.c:245
 msgid "Encoding should not be specified for inline data. It will be ignored."
 msgstr "La codificació no ha de ser especificada per les dades en línia. Serà ignorada."
 
-#: src/language/data-io/data-list.c:255
+#: src/language/data-io/data-list.c:254
 msgid "The END subcommand may be used only with DATA LIST FIXED."
 msgstr "El subcomando END només potser utilitzat amb DATA LIST FIXED."
 
-#: src/language/data-io/data-list.c:270
+#: src/language/data-io/data-list.c:269
 msgid "At least one variable must be specified."
 msgstr "Al menys una variable ha de ser especificada."
 
-#: src/language/data-io/data-list.c:369 src/language/data-io/data-list.c:458
+#: src/language/data-io/data-list.c:368 src/language/data-io/data-list.c:457
 #: src/language/data-io/get-data.c:540
 #, c-format
 msgid "%s is a duplicate variable name."
 msgstr "%s és un nom de variable duplicat."
 
-#: src/language/data-io/data-list.c:376
+#: src/language/data-io/data-list.c:375
 #, c-format
 msgid "There is already a variable %s of a different type."
 msgstr "Ja existeix una variable %s de diferent tipus."
 
-#: src/language/data-io/data-list.c:383
+#: src/language/data-io/data-list.c:382
 #, c-format
 msgid "There is already a string variable %s of a different width."
 msgstr "Ja existeix una cadena de la variable %s d'amplada diferent."
 
-#: src/language/data-io/data-list.c:391
+#: src/language/data-io/data-list.c:390
 #, c-format
 msgid "Cannot place variable %s on record %d when RECORDS=%d is specified."
 msgstr "No es pot posar la variable %s en el registre %d quan RECORDS=%d està especificat."
@@ -3396,6 +3428,23 @@ msgstr "S'ha produït un error en obrir `%s' per a escriure'l com a arxiu de dad
 msgid "I/O error occurred writing data file `%s'."
 msgstr "Error E/S en escriure les dades de l'arxiu `%s'."
 
+#: src/language/data-io/dataset.c:63
+#, c-format
+msgid "There is no dataset named %s."
+msgstr "No hi ha cap arxiu de dades anomenat %s."
+
+#: src/language/data-io/dataset.c:257
+msgid "Dataset"
+msgstr "Arxiu de dades"
+
+#: src/language/data-io/dataset.c:265
+msgid "unnamed dataset"
+msgstr "Arxiu de dades sense nom"
+
+#: src/language/data-io/dataset.c:269
+msgid "(active dataset)"
+msgstr "(arxiu de dades actiu)"
+
 #: src/language/data-io/get-data.c:64
 #, c-format
 msgid "Unsupported TYPE %s."
@@ -3758,58 +3807,58 @@ msgstr "Empíric"
 msgid "Empirical with averaging"
 msgstr "Empíric amb mitjanes"
 
-#: src/output/ascii.c:281
+#: src/output/ascii.c:298
 #, c-format
 msgid "%s: %s must be positive integer or `auto'"
 msgstr "%s: %s ha de ser enter positiu o `auto'"
 
-#: src/output/ascii.c:314
+#: src/output/ascii.c:331
 #, c-format
 msgid "ascii: page excluding margins and headers must be at least %d characters wide by %d lines long, but as configured is only %d characters by %d lines"
 msgstr "ascii: excloent els marges i encapçalaments la pàgina ha de tenir com a mínim %d caràcters d'ample per %d línies de llarg, però tal com està configurada, només n'hi ha %d caràcters i %d línies"
 
-#: src/output/ascii.c:363
+#: src/output/ascii.c:377
 #, c-format
 msgid "ascii: closing output file `%s'"
 msgstr "ascii: tancant l'arxiu de sortida `%s'"
 
-#: src/output/ascii.c:506
+#: src/output/ascii.c:520
 #, c-format
 msgid "See %s for a chart."
 msgstr "Veure %s per a gràfica."
 
-#: src/output/ascii.c:833
+#: src/output/ascii.c:1102
 #, c-format
 msgid "ascii: opening output file `%s'"
 msgstr "ascii: obrint l'arxiu de resultats `%s'"
 
-#: src/output/ascii.c:940
+#: src/output/ascii.c:1173
 #, c-format
 msgid "%s - Page %d"
 msgstr "%s - Pàgina %d"
 
-#: src/output/csv.c:97 src/output/html.c:106 src/output/journal.c:93
+#: src/output/csv.c:97 src/output/html.c:104 src/output/journal.c:93
 #: src/output/msglog.c:66
 #, c-format
 msgid "error opening output file `%s'"
 msgstr "error obrint l'arxiu de resultats `%s'"
 
 #. TRANSLATORS: Don't translate the words `terminal' or `listing'.
-#: src/output/driver.c:283
+#: src/output/driver.c:319
 #, c-format
 msgid "%s is not a valid device type (the choices are `terminal' and `listing')"
 msgstr "%s no és un tipus de dispositiu vàlid (les opcions son `terminal' i `listing')"
 
-#: src/output/driver.c:296
+#: src/output/driver.c:332
 #, c-format
 msgid "%s: unknown option `%s'"
 msgstr "%s: opció desconeguda `%s'"
 
-#: src/output/html.c:114
+#: src/output/html.c:112
 msgid "PSPP Output"
 msgstr "Resultat de PSPP"
 
-#: src/output/html.c:258
+#: src/output/html.c:238
 msgid "No description"
 msgstr "Sense descripció"
 
@@ -3960,7 +4009,7 @@ msgid "HISTOGRAM"
 msgstr "HISTOGRAM"
 
 #: src/output/charts/plot-hist-cairo.c:112
-#: src/language/stats/frequencies.q:824
+#: src/language/stats/frequencies.q:822
 msgid "Frequency"
 msgstr "Freqüència"
 
@@ -3988,11 +4037,11 @@ msgstr "L'algoritme ha de ser o ' compatible' o `enhanced'."
 msgid "Syntax must be either `compatible' or `enhanced'."
 msgstr "La sintaxi ha de ser o `compatible' o `enhanced'."
 
-#: src/ui/terminal/main.c:145
+#: src/ui/terminal/main.c:148
 msgid "Error encountered while ERROR=STOP is effective."
 msgstr "Detectat un error mentre està actiu ERROR=STOP."
 
-#: src/ui/terminal/main.c:151
+#: src/ui/terminal/main.c:154
 msgid "Stopping syntax file processing here to avoid a cascade of dependent command failures."
 msgstr "Aturant el processament de l'arxiu de sintaxi aquí per evitar una cascada d'errors derivats."
 
@@ -4087,13 +4136,13 @@ msgstr "no es pot accedir a la definició per a terminal `%s'"
 msgid "Aggregate destination file"
 msgstr "Arxiu destinació de l'agregació"
 
-#: src/ui/gui/aggregate-dialog.c:172 src/ui/gui/psppire-data-window.c:400
-#: src/ui/gui/psppire-data-window.c:601
+#: src/ui/gui/aggregate-dialog.c:172 src/ui/gui/psppire-data-window.c:489
+#: src/ui/gui/psppire-window.c:763
 msgid "System Files (*.sav)"
 msgstr "Arxius de Sistema (*.sav)"
 
-#: src/ui/gui/aggregate-dialog.c:178 src/ui/gui/psppire-data-window.c:406
-#: src/ui/gui/psppire-data-window.c:607
+#: src/ui/gui/aggregate-dialog.c:178 src/ui/gui/psppire-data-window.c:495
+#: src/ui/gui/psppire-window.c:769
 msgid "Portable Files (*.por) "
 msgstr "Arxius Portables (*.por)"
 
@@ -4162,7 +4211,7 @@ msgstr "Corr."
 
 #: src/ui/gui/crosstabs-dialog.c:53 src/ui/gui/crosstabs-dialog.c:64
 #: src/ui/gui/crosstabs-dialog.c:99 src/ui/gui/crosstabs-dialog.c:107
-#: src/ui/gui/psppire-var-store.c:613 src/ui/gui/var-display.c:16
+#: src/ui/gui/psppire-var-store.c:612 src/ui/gui/var-display.c:16
 #: src/ui/gui/variable-info-dialog.c:41
 msgid "None"
 msgstr "Cap"
@@ -4317,19 +4366,19 @@ msgstr "Especificació d'interval incorrecte"
 msgid "Contrast %d of %d"
 msgstr "Contrast %d de %d"
 
-#: src/ui/gui/psppire.c:218
+#: src/ui/gui/psppire.c:191
 msgid "_Reset"
 msgstr "_Reiniciar"
 
-#: src/ui/gui/psppire.c:219
+#: src/ui/gui/psppire.c:192
 msgid "_Select"
 msgstr "_Selecionar"
 
-#: src/ui/gui/psppire-data-editor.c:950
+#: src/ui/gui/psppire-data-editor.c:970
 msgid "Data View"
 msgstr "Vista de dades"
 
-#: src/ui/gui/psppire-data-editor.c:953
+#: src/ui/gui/psppire-data-editor.c:973
 msgid "Variable View"
 msgstr "Vista de Variables"
 
@@ -4337,71 +4386,73 @@ msgstr "Vista de Variables"
 msgid "var"
 msgstr "var"
 
-#: src/ui/gui/psppire-data-window.c:212
+#: src/ui/gui/psppire-data-window.c:202
 msgid "Transformations Pending"
 msgstr "Transformacions pendents"
 
-#: src/ui/gui/psppire-data-window.c:228
+#: src/ui/gui/psppire-data-window.c:218
 msgid "Filter off"
 msgstr "Filtre desactivat"
 
-#: src/ui/gui/psppire-data-window.c:242
+#: src/ui/gui/psppire-data-window.c:232
 #, c-format
 msgid "Filter by %s"
 msgstr "Filtrat per %s"
 
-#: src/ui/gui/psppire-data-window.c:263
+#: src/ui/gui/psppire-data-window.c:253
 msgid "No Split"
 msgstr "No dividit"
 
-#: src/ui/gui/psppire-data-window.c:272
+#: src/ui/gui/psppire-data-window.c:262
 msgid "Split by "
 msgstr "Dividit per "
 
-#: src/ui/gui/psppire-data-window.c:300
+#: src/ui/gui/psppire-data-window.c:290
 msgid "Weights off"
 msgstr "Sense Ponderar:"
 
-#: src/ui/gui/psppire-data-window.c:314
+#: src/ui/gui/psppire-data-window.c:304
 #, c-format
 msgid "Weight by %s"
 msgstr "Ponderat per %s"
 
-#: src/ui/gui/psppire-data-window.c:380
-msgid "Open"
-msgstr "Obert"
-
-#: src/ui/gui/psppire-data-window.c:390
-msgid "Data and Syntax Files"
-msgstr "Arxius de Dades i Sintaxi"
-
-#: src/ui/gui/psppire-data-window.c:412 src/ui/gui/psppire-syntax-window.c:505
-msgid "Syntax Files (*.sps) "
-msgstr "Arxius de Sintàxi (*.sps) "
+#: src/ui/gui/psppire-data-window.c:481 src/ui/gui/aggregate.ui:448
+msgid "Save"
+msgstr "Desar"
 
-#: src/ui/gui/psppire-data-window.c:418 src/ui/gui/psppire-data-window.c:613
-#: src/ui/gui/psppire-syntax-window.c:511
+#: src/ui/gui/psppire-data-window.c:501 src/ui/gui/psppire-syntax-window.c:508
+#: src/ui/gui/psppire-window.c:781
 msgid "All Files"
 msgstr "Tots els arxius"
 
-#: src/ui/gui/psppire-data-window.c:593 src/ui/gui/aggregate.ui:448
-msgid "Save"
-msgstr "Desar"
-
-#: src/ui/gui/psppire-data-window.c:626
+#: src/ui/gui/psppire-data-window.c:514
 msgid "Portable File"
 msgstr "Arxiu Portable"
 
-#: src/ui/gui/psppire-data-window.c:759
+#: src/ui/gui/psppire-data-window.c:571
+msgid "Delete Existing Dataset?"
+msgstr "Eliminar arxiu de dades existent?"
+
+#: src/ui/gui/psppire-data-window.c:575
+#, c-format
+msgid "Renaming \"%s\" to \"%s\" will delete destroy the existing dataset named \"%s\".  Are you sure that you want to do this?"
+msgstr "Re-anomenar \"%s\" com a \"%s\" eliminarà l'arxiu existent anomenat \"%s\".  Esta segur que vol fer aixó?"
+
+#: src/ui/gui/psppire-data-window.c:603
+#, c-format
+msgid "Please enter a new name for dataset \"%s\":"
+msgstr "Si us plau, introdueixi un nou nom per l'arxiu de dades \"%s\":"
+
+#: src/ui/gui/psppire-data-window.c:605
+msgid "Rename Dataset"
+msgstr "Reanomena l'Arxiu de dades"
+
+#: src/ui/gui/psppire-data-window.c:684
 msgid "Font Selection"
 msgstr "Selecció de font"
 
 #. TRANSLATORS: This will form a filename.  Please avoid whitespace.
-#: src/ui/gui/psppire-data-window.c:1256
-msgid "PSPP-data"
-msgstr "datos-PSPP"
-
-#: src/ui/gui/psppire-data-window.c:1257
+#: src/ui/gui/psppire-data-window.c:1287
 msgid "Data Editor"
 msgstr "Editor de Dades"
 
@@ -4462,25 +4513,25 @@ msgstr "Resultats"
 msgid "Output Viewer"
 msgstr "Vista de resultats"
 
-#: src/ui/gui/psppire-syntax-window.c:478
+#: src/ui/gui/psppire-syntax-window.c:475
 #, c-format
 msgid "Saved file `%s'"
 msgstr "Desat com a arxiu `%s'"
 
-#: src/ui/gui/psppire-syntax-window.c:497
+#: src/ui/gui/psppire-syntax-window.c:494
 msgid "Save Syntax"
 msgstr "Desar sintaxi"
 
-#. TRANSLATORS: This will form a filename.  Please avoid whitespace.
-#: src/ui/gui/psppire-syntax-window.c:746
-msgid "Syntax"
-msgstr "Sintaxi"
+#: src/ui/gui/psppire-syntax-window.c:502 src/ui/gui/psppire-window.c:775
+msgid "Syntax Files (*.sps) "
+msgstr "Arxius de Sintàxi (*.sps) "
 
-#: src/ui/gui/psppire-syntax-window.c:747
+#. TRANSLATORS: This will form a filename.  Please avoid whitespace.
+#: src/ui/gui/psppire-syntax-window.c:733
 msgid "Syntax Editor"
 msgstr "Editor de sintaxi"
 
-#: src/ui/gui/psppire-syntax-window.c:761
+#: src/ui/gui/psppire-syntax-window.c:747
 #, c-format
 msgid "Cannot load syntax file `%s'"
 msgstr "No es pot obrir l'arxiu de sintaxi `%s'"
@@ -4505,7 +4556,7 @@ msgstr "Valores"
 
 #: src/ui/gui/psppire-var-sheet.c:540 src/ui/gui/psppire-var-store.c:839
 #: src/language/stats/crosstabs.q:831 src/language/stats/examine.q:1103
-#: src/language/stats/frequencies.q:874 src/language/stats/frequencies.q:1045
+#: src/language/stats/frequencies.q:872 src/language/stats/frequencies.q:1043
 msgid "Missing"
 msgstr "Perduts"
 
@@ -4517,59 +4568,57 @@ msgstr "Aliniament"
 msgid "Measure"
 msgstr "Mesura"
 
-#: src/ui/gui/psppire-var-store.c:623 src/ui/gui/var-sheet-dialogs.ui:43
+#: src/ui/gui/psppire-var-store.c:622 src/ui/gui/var-sheet-dialogs.ui:43
 msgid "Comma"
 msgstr "Coma"
 
-#: src/ui/gui/psppire-var-store.c:624 src/ui/gui/var-sheet-dialogs.ui:59
+#: src/ui/gui/psppire-var-store.c:623 src/ui/gui/var-sheet-dialogs.ui:59
 msgid "Dot"
 msgstr "Punt"
 
-#: src/ui/gui/psppire-var-store.c:625
+#: src/ui/gui/psppire-var-store.c:624
 msgid "Scientific"
 msgstr "Científic"
 
-#: src/ui/gui/psppire-var-store.c:626 src/ui/gui/var-sheet-dialogs.ui:91
+#: src/ui/gui/psppire-var-store.c:625 src/ui/gui/var-sheet-dialogs.ui:91
 msgid "Date"
 msgstr "Data"
 
-#: src/ui/gui/psppire-var-store.c:627 src/ui/gui/var-sheet-dialogs.ui:107
+#: src/ui/gui/psppire-var-store.c:626 src/ui/gui/var-sheet-dialogs.ui:107
 msgid "Dollar"
 msgstr "Dolar"
 
-#: src/ui/gui/psppire-var-store.c:628
+#: src/ui/gui/psppire-var-store.c:627
 msgid "Custom"
 msgstr "Usuari"
 
-#: src/ui/gui/psppire-var-store.c:756
+#: src/ui/gui/psppire-var-store.c:755
 #, c-format
 msgid "{%s,`%s'}_"
 msgstr "{%s,`%s'}_"
 
-#: src/ui/gui/psppire-window.c:97
-#, c-format
-msgid "%s %s PSPPIRE %s"
-msgstr "%s %s PSPPIRE %s"
-
-#. TRANSLATORS: This will form a filename.  Please avoid whitespace.
-#: src/ui/gui/psppire-window.c:247
-msgid "Untitled"
-msgstr "Sense titol"
-
-#: src/ui/gui/psppire-window.c:469
+#: src/ui/gui/psppire-window.c:549
 #, c-format
 msgid "Save the changes to `%s' before closing?"
 msgstr "Desa el canvis a `%s' abans de sortir?"
 
-#: src/ui/gui/psppire-window.c:476
+#: src/ui/gui/psppire-window.c:556
 #, c-format
 msgid "If you don't save, changes from the last %ld seconds will be permanently lost."
 msgstr "Si no es desa, els canvis dels darrers %ld segons es perdran permanentment."
 
-#: src/ui/gui/psppire-window.c:480
+#: src/ui/gui/psppire-window.c:560
 msgid "Close _without saving"
 msgstr "Tancar sense desar"
 
+#: src/ui/gui/psppire-window.c:743
+msgid "Open"
+msgstr "Obert"
+
+#: src/ui/gui/psppire-window.c:753
+msgid "Data and Syntax Files"
+msgstr "Arxius de Dades i Sintaxi"
+
 #: src/ui/gui/recode-dialog.c:886
 msgid "Recode into Different Variables"
 msgstr "Recodifica en variables Diferents"
@@ -4625,45 +4674,45 @@ msgstr "Exactament %3d casos dels primers  %3d casos."
 msgid "%d thru %d"
 msgstr "%d fisn a %d"
 
-#: src/ui/gui/text-data-import-dialog.c:452
+#: src/ui/gui/text-data-import-dialog.c:453
 #, c-format
 msgid "Could not open `%s': %s"
 msgstr "No es pot obrir `%s': %s"
 
-#: src/ui/gui/text-data-import-dialog.c:468
+#: src/ui/gui/text-data-import-dialog.c:469
 #, c-format
 msgid "Error reading `%s': %s"
 msgstr "Error leyendo `%s': %s"
 
-#: src/ui/gui/text-data-import-dialog.c:471
+#: src/ui/gui/text-data-import-dialog.c:472
 #, c-format
 msgid "Failed to read `%s', because it contains a line over %d bytes long and therefore appears not to be a text file."
 msgstr "Error en llegir `%s', per què conté una linia per sobre dels %d bytes de llarg i, per tant, sembla que no és un arxiu de text."
 
-#: src/ui/gui/text-data-import-dialog.c:485
+#: src/ui/gui/text-data-import-dialog.c:486
 #, c-format
 msgid "`%s' is empty."
 msgstr "`%s' és buit."
 
-#: src/ui/gui/text-data-import-dialog.c:530
+#: src/ui/gui/text-data-import-dialog.c:531
 msgid "Import Delimited Text Data"
 msgstr "Importar dades de text delimitat"
 
-#: src/ui/gui/text-data-import-dialog.c:581
+#: src/ui/gui/text-data-import-dialog.c:582
 msgid "Importing Delimited Text Data"
 msgstr "Important dades de text deliminatat"
 
-#: src/ui/gui/text-data-import-dialog.c:730
+#: src/ui/gui/text-data-import-dialog.c:731
 #, c-format
 msgid "Only the first %4d cases"
 msgstr "Només els primers %4d casos"
 
-#: src/ui/gui/text-data-import-dialog.c:740
+#: src/ui/gui/text-data-import-dialog.c:741
 #, c-format
 msgid "Only the first %3d %% of file (approximately)"
 msgstr "Només els primers %3ds %% de l'arxiu (aproximadament)"
 
-#: src/ui/gui/text-data-import-dialog.c:765
+#: src/ui/gui/text-data-import-dialog.c:766
 msgid ""
 "This assistant will guide you through the process of importing data into PSPP from a text file with one line per case,  in which fields are separated by tabs, commas, or other delimiters.\n"
 "\n"
@@ -4671,46 +4720,46 @@ msgstr ""
 "Aquest asistent t'acompanyarà per tot el procés d'importar dades cap al PSPP a partir d'un arxiu de text amb una linia per cas,  al qual els camps estan separats per tabuladors, comes, o altres delimitadors.\n"
 "\n"
 
-#: src/ui/gui/text-data-import-dialog.c:771
+#: src/ui/gui/text-data-import-dialog.c:772
 #, c-format
 msgid "The selected file contains %zu line of text.  "
 msgid_plural "The selected file contains %zu lines of text.  "
 msgstr[0] "L'arxiu seleccionat conté %zu linies de text.  "
 msgstr[1] "L'arxiu seleccionat conté %zu linies de text.  "
 
-#: src/ui/gui/text-data-import-dialog.c:779
+#: src/ui/gui/text-data-import-dialog.c:780
 #, c-format
 msgid "The selected file contains approximately %lu line of text.  "
 msgid_plural "The selected file contains approximately %lu lines of text.  "
 msgstr[0] "L'arxiu seleccionat conté aproximadament %lu linia de text.  "
 msgstr[1] "L'arxiu seleccionat conté aproximadament %lu linies de text.  "
 
-#: src/ui/gui/text-data-import-dialog.c:785
+#: src/ui/gui/text-data-import-dialog.c:786
 #, c-format
 msgid "Only the first %zu line of the file will be shown for preview purposes in the following screens.  "
 msgid_plural "Only the first %zu lines of the file will be shown for preview purposes in the following screens.  "
 msgstr[0] "Només les primeres %zu linies de l'arxiu es previsualitzaran a les seguents pantalles.  "
 msgstr[1] "Només les primeres %zu linies de l'arxiu es previsualitzaran a les seguents pantalles.  "
 
-#: src/ui/gui/text-data-import-dialog.c:792
+#: src/ui/gui/text-data-import-dialog.c:793
 msgid "You may choose below how much of the file should actually be imported."
 msgstr "Pots triar a continuació quina part de l'arxiu ha de ser importat."
 
-#: src/ui/gui/text-data-import-dialog.c:875
+#: src/ui/gui/text-data-import-dialog.c:876
 msgid "Text"
 msgstr "Text"
 
-#: src/ui/gui/text-data-import-dialog.c:1539
-#: src/ui/gui/text-data-import-dialog.c:1785
+#: src/ui/gui/text-data-import-dialog.c:1540
+#: src/ui/gui/text-data-import-dialog.c:1786
 msgid "This input line has too few separators to fill in this field."
 msgstr "Aquesta linia d'entrada no en te prou separadors per emplenar el camp"
 
-#: src/ui/gui/text-data-import-dialog.c:1776
+#: src/ui/gui/text-data-import-dialog.c:1777
 #, c-format
 msgid "Cannot parse field content `%.*s' as format %s: %s"
 msgstr "No es possible construïr l'arxiu de contingut `%.*s' com a format %s: %s"
 
-#: src/ui/gui/text-data-import-dialog.c:1929
+#: src/ui/gui/text-data-import-dialog.c:1930
 msgid "Line"
 msgstr "Linia"
 
@@ -4719,7 +4768,7 @@ msgstr "Linia"
 msgid "Confidence Interval: %2d %%"
 msgstr "Interval de Confiança: %2d %%"
 
-#: src/ui/gui/val-labs-dialog.c:515
+#: src/ui/gui/val-labs-dialog.c:519
 #, c-format
 msgid "%s = `%s'"
 msgstr "%s = `%s'"
@@ -4739,16 +4788,16 @@ msgstr "Tipus: %s\n"
 msgid "Missing Values: %s\n"
 msgstr "Valors perduts: %s\n"
 
-#: src/ui/gui/variable-info-dialog.c:93
+#: src/ui/gui/variable-info-dialog.c:92
 #, c-format
 msgid "Measurement Level: %s\n"
 msgstr "Nivel de Mesura: %s\n"
 
-#: src/ui/gui/variable-info-dialog.c:106
+#: src/ui/gui/variable-info-dialog.c:105
 msgid "Value Labels:\n"
 msgstr "Etiqueteas de valor:\n"
 
-#: src/ui/gui/variable-info-dialog.c:116
+#: src/ui/gui/variable-info-dialog.c:115
 #, c-format
 msgid "%s %s\n"
 msgstr "%s %s\n"
@@ -4933,7 +4982,7 @@ msgid "Summary."
 msgstr "Resum."
 
 #: src/language/stats/crosstabs.q:840 src/language/stats/examine.q:1178
-#: src/language/stats/frequencies.q:825
+#: src/language/stats/frequencies.q:823
 msgid "Percent"
 msgstr "Percentatge"
 
@@ -5185,113 +5234,113 @@ msgstr "Bisagras de Tukey"
 msgid "%g"
 msgstr "%g"
 
-#: src/language/stats/frequencies.q:382
+#: src/language/stats/frequencies.q:381
 msgid "Bar charts are not implemented."
 msgstr "El gràfic de barres no està implementat."
 
-#: src/language/stats/frequencies.q:399
+#: src/language/stats/frequencies.q:398
 #, c-format
 msgid "MAX for histogram must be greater than or equal to MIN, but MIN was specified as %.15g and MAX as %.15g.  MIN and MAX will be ignored."
 msgstr "Per l'histograma, MAX ha de ser major o igual a MIN, però MIN s'ha especificat com a %.15g i MAX com a %.15g.  MIN i MAX seràn ignorats."
 
-#: src/language/stats/frequencies.q:420
+#: src/language/stats/frequencies.q:419
 #, c-format
 msgid "MAX for pie chart must be greater than or equal to MIN, but MIN was specified as %.15g and MAX as %.15g.  MIN and MAX will be ignored."
 msgstr "Per grafica de sectors, MAX ha de ser major o igual a MIN, però MIN s'ha especificat com a %.15g i MAX com a %.15g.  MIN i MAX seràn ignorats."
 
-#: src/language/stats/frequencies.q:704
+#: src/language/stats/frequencies.q:702
 msgid "`)' expected after GROUPED interval list."
 msgstr "`)' esperat després de la llista de variables GRUPED."
 
-#: src/language/stats/frequencies.q:724
+#: src/language/stats/frequencies.q:722
 #, c-format
 msgid "Variables %s specified multiple times on GROUPED subcommand."
 msgstr "La variable %s s'ha especificat més d'una vegada a l'ordre GROUPED."
 
-#: src/language/stats/frequencies.q:734
+#: src/language/stats/frequencies.q:732
 #, c-format
 msgid "Variables %s specified on GROUPED but not on VARIABLES."
 msgstr "Variables %s especificades a GROUPED però no a VARIABLES."
 
-#: src/language/stats/frequencies.q:822
+#: src/language/stats/frequencies.q:820
 msgid "Value Label"
 msgstr "Etiqueta de Valor"
 
-#: src/language/stats/frequencies.q:826
+#: src/language/stats/frequencies.q:824
 msgid "Valid Percent"
 msgstr "Percentatge Vàlid"
 
-#: src/language/stats/frequencies.q:827
+#: src/language/stats/frequencies.q:825
 msgid "Cum Percent"
 msgstr "Percentatge Acumulat"
 
-#: src/language/stats/frequencies.q:1017
+#: src/language/stats/frequencies.q:1015
 #, c-format
 msgid "No valid data for variable %s; statistics not displayed."
 msgstr "No hi ha dades vàlides per a la variable %s; not es mostren estadístiques."
 
-#: src/language/stats/frequencies.q:1063
+#: src/language/stats/frequencies.q:1061
 msgid "50 (Median)"
 msgstr "50 (Mediana)"
 
-#: src/language/stats/frequencies.q:1218
+#: src/language/stats/frequencies.q:1217
 #, c-format
 msgid "Omitting pie chart for %s, which has only %d unique values."
 msgstr "S'omet grafic de sectors per a %s, que només té %d valors únics. "
 
-#: src/language/stats/frequencies.q:1221
+#: src/language/stats/frequencies.q:1220
 #, c-format
 msgid "Omitting pie chart for %s, which has over 50 unique values."
 msgstr "S'omet grafic de sectors per a %s, que té més de 50 valors únics. "
 
-#: src/language/stats/rank.q:220
+#: src/language/stats/rank.q:219
 #, c-format
 msgid "%s of %s by %s"
 msgstr "%s de %s per %s"
 
-#: src/language/stats/rank.q:225
+#: src/language/stats/rank.q:224
 #, c-format
 msgid "%s of %s"
 msgstr "%s de %s"
 
-#: src/language/stats/rank.q:600
+#: src/language/stats/rank.q:599
 msgid "Cannot create new rank variable.  All candidates in use."
 msgstr "No es pot crear la nova variable de rangs.  Tots els candidats estan en ús."
 
-#: src/language/stats/rank.q:696
+#: src/language/stats/rank.q:694
 msgid "Variables Created By RANK"
 msgstr "Variables creades per RANK"
 
-#: src/language/stats/rank.q:720
+#: src/language/stats/rank.q:718
 #, c-format
 msgid "%s into %s(%s of %s using %s BY %s)"
 msgstr "%s en %s(%s de %s utilitzant %s BY %s)"
 
-#: src/language/stats/rank.q:730
+#: src/language/stats/rank.q:728
 #, c-format
 msgid "%s into %s(%s of %s BY %s)"
 msgstr "%s en %s(%s de %s BY %s)"
 
-#: src/language/stats/rank.q:743
+#: src/language/stats/rank.q:741
 #, c-format
 msgid "%s into %s(%s of %s using %s)"
 msgstr "%s en %s(%s de %s utilitzant %s)"
 
-#: src/language/stats/rank.q:752
+#: src/language/stats/rank.q:750
 #, c-format
 msgid "%s into %s(%s of %s)"
 msgstr "%s en %s(%s de %s)"
 
-#: src/language/stats/rank.q:764
+#: src/language/stats/rank.q:762
 msgid "FRACTION has been specified, but NORMAL and PROPORTION rank functions have not been requested.  The FRACTION subcommand will be ignored."
 msgstr "S'ha especificat FRACTION, però no s'ahn demanat funcions de rang NORMAL o PROPORTION.  La  subordre FRACTION será ignorada."
 
-#: src/language/stats/rank.q:855
+#: src/language/stats/rank.q:853
 #, c-format
 msgid "Variable %s already exists."
 msgstr "La variable %s ja existeix."
 
-#: src/language/stats/rank.q:860
+#: src/language/stats/rank.q:858
 msgid "Too many variables in INTO clause."
 msgstr "Massa variables a la clausula INTO."
 
@@ -5465,38 +5514,38 @@ msgstr "Correlació"
 msgid "%s & %s"
 msgstr "%s & %s"
 
-#: src/language/data-io/file-handle.q:68
+#: src/language/data-io/file-handle.q:70
 #, c-format
 msgid "File handle %s is already defined.  Use CLOSE FILE HANDLE before redefining a file handle."
 msgstr "El manipulador d'arxiu %s ja ha esta definit.  Utilitzar CLOSE FILE HANDLE abans de redefinir un manipulador d'arxius."
 
-#: src/language/data-io/file-handle.q:123
+#: src/language/data-io/file-handle.q:122
 msgid "RECFORM must be specified with MODE=360."
 msgstr "RECFORM ha de ser espeficat amb MODE=360."
 
-#: src/language/data-io/file-handle.q:134
+#: src/language/data-io/file-handle.q:133
 #, c-format
 msgid "The specified file mode requires LRECL.  Assuming %zu-character records."
 msgstr "El mode d'arxiu especificat requereix LRECL.  S'asumeix registres de %zu caracters."
 
-#: src/language/data-io/file-handle.q:138
+#: src/language/data-io/file-handle.q:137
 #, c-format
-msgid "Record length (%ld) must be between 1 and %lu bytes.  Assuming %d-character records."
-msgstr "L'amplada de registre (%ld) ha d'estar entre  1 i %lu bytes.  S'asumeix %d-registres de caracter."
+msgid "Record length (%ld) must be between 1 and %lu bytes.  Assuming %zu-character records."
+msgstr "L'amplada de registre (%ld) ha d'estar entre  1 i %lu bytes.  S'asumeix %zu-registres de caracter."
 
-#: src/language/data-io/file-handle.q:182
+#: src/language/data-io/file-handle.q:178
 msgid "file"
 msgstr "arxiu"
 
-#: src/language/data-io/file-handle.q:184
+#: src/language/data-io/file-handle.q:180
 msgid "inline file"
 msgstr "arxiu en linia"
 
-#: src/language/data-io/file-handle.q:210
+#: src/language/data-io/file-handle.q:228
 msgid "expecting a file name or handle name"
 msgstr "experant un nom d'arxiu o un manipulador"
 
-#: src/language/data-io/file-handle.q:231
+#: src/language/data-io/file-handle.q:243
 #, c-format
 msgid "Handle for %s not allowed here."
 msgstr "Aquí no està permès un manipulador per a %s."
@@ -5862,7 +5911,7 @@ msgstr "Factors pels eixos principals"
 msgid "Factor Analysis"
 msgstr "Anàlisi Factorial"
 
-#: src/ui/gui/factor.ui:55
+#: src/ui/gui/factor.ui:55 src/ui/gui/data-editor.ui:343
 msgid "_Descriptives..."
 msgstr "_Descriptius..."
 
@@ -6124,7 +6173,7 @@ msgstr "_Factor:"
 msgid "Dependent _Variable(s):"
 msgstr "_Variable(s) Depenents:"
 
-#: src/ui/gui/oneway.ui:184 src/ui/gui/data-editor.ui:332
+#: src/ui/gui/oneway.ui:184
 msgid "_Descriptives"
 msgstr "_Descriptives"
 
@@ -6816,323 +6865,376 @@ msgid "_File"
 msgstr "_Arxiu"
 
 #: src/ui/gui/data-editor.ui:35 src/ui/gui/syntax-editor.ui:22
-#: src/ui/gui/syntax-editor.ui:40
 msgid "_Syntax"
 msgstr "_Sintaxi"
 
-#: src/ui/gui/data-editor.ui:41 src/ui/gui/data-editor.ui:214
-#: src/ui/gui/data-editor.ui:226 src/ui/gui/syntax-editor.ui:28
-#: src/ui/gui/syntax-editor.ui:46
+#: src/ui/gui/data-editor.ui:41 src/ui/gui/data-editor.ui:224
+#: src/ui/gui/data-editor.ui:237 src/ui/gui/syntax-editor.ui:28
 msgid "_Data"
 msgstr "_Dades"
 
-#: src/ui/gui/data-editor.ui:53
-msgid "_Import Delimited Text Data"
-msgstr "_Importar dades de text delimitat"
+#: src/ui/gui/data-editor.ui:48 src/ui/gui/syntax-editor.ui:35
+msgid "_Open..."
+msgstr "_Obert..."
+
+#: src/ui/gui/data-editor.ui:54
+msgid "_Import Delimited Text Data..."
+msgstr "_Importar Dades de Text Delimitat..."
+
+#: src/ui/gui/data-editor.ui:61
+msgid "_Rename Dataset..."
+msgstr "_Reanomenar l'arxiu de dades..."
 
-#: src/ui/gui/data-editor.ui:72
+#: src/ui/gui/data-editor.ui:74 src/ui/gui/syntax-editor.ui:48
+msgid "Save _As..."
+msgstr "Desar Com _A..."
+
+#: src/ui/gui/data-editor.ui:80
 msgid "D_isplay Data File Information"
 msgstr "Mostra _informació de l'arxiu de dades"
 
-#: src/ui/gui/data-editor.ui:79
+#: src/ui/gui/data-editor.ui:87
 msgid "Working File"
 msgstr "Arxius de treball"
 
-#: src/ui/gui/data-editor.ui:85
-msgid "External File"
-msgstr "Arxiu extern"
+#: src/ui/gui/data-editor.ui:93
+msgid "External File..."
+msgstr "Arxiu Extern..."
 
-#: src/ui/gui/data-editor.ui:91
+#: src/ui/gui/data-editor.ui:99
 msgid "Recently Used Da_ta"
 msgstr "Dades usades recentment"
 
-#: src/ui/gui/data-editor.ui:97
+#: src/ui/gui/data-editor.ui:105
 msgid "Recently Used _Files"
 msgstr "Arxius utilitzats recentment"
 
-#: src/ui/gui/data-editor.ui:109 src/ui/gui/output-viewer.ui:28
-#: src/ui/gui/syntax-editor.ui:70
+#: src/ui/gui/data-editor.ui:117 src/ui/gui/output-viewer.ui:29
+#: src/ui/gui/syntax-editor.ui:60
 msgid "_Edit"
 msgstr "_Editar"
 
-#: src/ui/gui/data-editor.ui:115
+#: src/ui/gui/data-editor.ui:123
 msgid "Insert Variable"
 msgstr "Insertar Variable"
 
-#: src/ui/gui/data-editor.ui:116
+#: src/ui/gui/data-editor.ui:124
 msgid "Create a new variable at the current position"
 msgstr "Crear una nova variable a la posició seleccionada"
 
-#: src/ui/gui/data-editor.ui:123
+#: src/ui/gui/data-editor.ui:131
 msgid "Insert Cases"
 msgstr "Insertar Casos"
 
-#: src/ui/gui/data-editor.ui:124
+#: src/ui/gui/data-editor.ui:132
 msgid "Create a new case at the current position"
 msgstr "Crear un nou cas a la posició actual"
 
-#: src/ui/gui/data-editor.ui:130
-msgid "Go To Case"
-msgstr "Anar a"
+#: src/ui/gui/data-editor.ui:138
+msgid "Go To Case..."
+msgstr "Anar al Cas..."
 
-#: src/ui/gui/data-editor.ui:132
+#: src/ui/gui/data-editor.ui:140
 msgid "Jump to a case in the data sheet"
 msgstr "Anar a un cas a la matriu de Dades"
 
-#: src/ui/gui/data-editor.ui:158
+#: src/ui/gui/data-editor.ui:166
 msgid "Cl_ear Variables"
 msgstr "_Eliminar Variables:"
 
-#: src/ui/gui/data-editor.ui:159
+#: src/ui/gui/data-editor.ui:167
 msgid "Delete the variables at the selected position(s)"
 msgstr "Esborra les variables a la posició(ns) selecconada(es)"
 
-#: src/ui/gui/data-editor.ui:167
+#: src/ui/gui/data-editor.ui:175
 msgid "_Clear Cases"
 msgstr "_Eliminar Casos"
 
-#: src/ui/gui/data-editor.ui:168
+#: src/ui/gui/data-editor.ui:176
 msgid "Delete the cases at the selected position(s)"
 msgstr "Esborra els casos a la(es) posició(ns) seleccionada(es)"
 
-#: src/ui/gui/data-editor.ui:180
+#: src/ui/gui/data-editor.ui:183
+msgid "_Find..."
+msgstr "Cercar..."
+
+#: src/ui/gui/data-editor.ui:189
 msgid "_View"
 msgstr "_Veure"
 
-#: src/ui/gui/data-editor.ui:187
+#: src/ui/gui/data-editor.ui:196
 msgid "_Status Bar"
 msgstr "Barra d'E_stat"
 
-#: src/ui/gui/data-editor.ui:200
+#: src/ui/gui/data-editor.ui:203
+msgid "_Font..."
+msgstr "_Font..."
+
+#: src/ui/gui/data-editor.ui:210
 msgid "_Grid Lines"
 msgstr "_Linies divisories"
 
-#: src/ui/gui/data-editor.ui:206
+#: src/ui/gui/data-editor.ui:216
 msgid "Value _Labels"
 msgstr "Etiquetes de _Valors"
 
-#: src/ui/gui/data-editor.ui:207
+#: src/ui/gui/data-editor.ui:217
 msgid "Show/hide value labels"
 msgstr "Mostra/Oculta etiquetes de valor"
 
-#: src/ui/gui/data-editor.ui:220 src/ui/gui/data-editor.ui:440
+#: src/ui/gui/data-editor.ui:230
 msgid "_Variables"
 msgstr "_Variables:"
 
-#: src/ui/gui/data-editor.ui:231
-msgid "_Sort Cases"
-msgstr "_Ordenar Casos"
+#: src/ui/gui/data-editor.ui:242
+msgid "_Sort Cases..."
+msgstr "Ordenar Cassos..."
 
-#: src/ui/gui/data-editor.ui:234
+#: src/ui/gui/data-editor.ui:245
 msgid "Sort cases in the active dataset"
 msgstr "Ordenar casos a l'arxiu de dades actiu"
 
-#: src/ui/gui/data-editor.ui:241
-msgid "_Transpose"
-msgstr "_Transposar"
+#: src/ui/gui/data-editor.ui:252
+msgid "_Transpose..."
+msgstr "_Transposar..."
 
-#: src/ui/gui/data-editor.ui:242
+#: src/ui/gui/data-editor.ui:253
 msgid "Transpose the cases with the variables"
 msgstr "Transposar casos i variables"
 
-#: src/ui/gui/data-editor.ui:249
-msgid "_Aggregate"
-msgstr "_Agregar"
+#: src/ui/gui/data-editor.ui:260
+msgid "_Aggregate..."
+msgstr "_Agregar..."
 
-#: src/ui/gui/data-editor.ui:255
-msgid "S_plit File"
-msgstr "Divideix Arxiu"
+#: src/ui/gui/data-editor.ui:266
+msgid "S_plit File..."
+msgstr "Divideix Arxiu..."
 
-#: src/ui/gui/data-editor.ui:256
+#: src/ui/gui/data-editor.ui:267
 msgid "Split the active dataset"
 msgstr "Dividir l'arxiu de dades actiu"
 
-#: src/ui/gui/data-editor.ui:263
-msgid "Select _Cases"
-msgstr "Seleccionar _Casos"
+#: src/ui/gui/data-editor.ui:274
+msgid "Select _Cases..."
+msgstr "Seleccionar _Cassos..."
 
-#: src/ui/gui/data-editor.ui:269
-msgid "_Weight Cases"
-msgstr "Pondera Cassos"
+#: src/ui/gui/data-editor.ui:280
+msgid "_Weight Cases..."
+msgstr "Ponderar Cassos..."
 
-#: src/ui/gui/data-editor.ui:270
+#: src/ui/gui/data-editor.ui:281
 msgid "Weight cases by variable"
 msgstr "Pondera casos per la variable"
 
-#: src/ui/gui/data-editor.ui:277
+#: src/ui/gui/data-editor.ui:288
 msgid "_Transform"
 msgstr "_Transformar"
 
-#: src/ui/gui/data-editor.ui:283
-msgid "_Compute"
-msgstr "_Calcular"
+#: src/ui/gui/data-editor.ui:294
+msgid "_Compute..."
+msgstr "_Calcular..."
 
-#: src/ui/gui/data-editor.ui:289
-msgid "Ran_k Cases"
-msgstr "Rang de casos"
+#: src/ui/gui/data-editor.ui:300
+msgid "Ran_k Cases..."
+msgstr "Rang de Cassos..."
 
-#: src/ui/gui/data-editor.ui:295
-msgid "Recode into _Same Variables"
-msgstr "Recodificar a les Mateixe_s Variables"
+#: src/ui/gui/data-editor.ui:306
+msgid "Recode into _Same Variables..."
+msgstr "Recodificar a les Mateixe_s Variables..."
 
-#: src/ui/gui/data-editor.ui:301
-msgid "Recode into _Different Variables"
-msgstr "Recodificar a variables _Diferents"
+#: src/ui/gui/data-editor.ui:312
+msgid "Recode into _Different Variables..."
+msgstr "Recodificar a Variables _Diferents..."
 
-#: src/ui/gui/data-editor.ui:307
+#: src/ui/gui/data-editor.ui:318
 msgid "_Run Pending Transforms"
 msgstr "Executa_r Transformacions pendents"
 
-#: src/ui/gui/data-editor.ui:314
+#: src/ui/gui/data-editor.ui:325
 msgid "_Analyze"
 msgstr "_Analitzar"
 
-#: src/ui/gui/data-editor.ui:320
+#: src/ui/gui/data-editor.ui:331
 msgid "_Descriptive Statistics"
 msgstr "Estadística _Descriptiva"
 
-#: src/ui/gui/data-editor.ui:326
-msgid "_Frequencies"
-msgstr "_Freqüències"
+#: src/ui/gui/data-editor.ui:337
+msgid "_Frequencies..."
+msgstr "_Freqüències..."
 
-#: src/ui/gui/data-editor.ui:338
-msgid "_Explore"
-msgstr "_Explorar"
+#: src/ui/gui/data-editor.ui:349
+msgid "_Explore..."
+msgstr "_Explorar..."
 
-#: src/ui/gui/data-editor.ui:344
-msgid "_Crosstabs"
-msgstr "_Creuaments tabulars"
+#: src/ui/gui/data-editor.ui:355
+msgid "_Crosstabs..."
+msgstr "Taules _Creuades..."
 
-#: src/ui/gui/data-editor.ui:350
+#: src/ui/gui/data-editor.ui:361
 msgid "Compare _Means"
 msgstr "Comparar _Mitjanes"
 
-#: src/ui/gui/data-editor.ui:356
-msgid "_One Sample T Test"
-msgstr "Prova T per una mostra"
+#: src/ui/gui/data-editor.ui:367
+msgid "_One Sample T Test..."
+msgstr "Prova T per una mostra..."
 
-#: src/ui/gui/data-editor.ui:362
-msgid "_Independent Samples T Test"
-msgstr "Prova T per mostres _Independents"
+#: src/ui/gui/data-editor.ui:373
+msgid "_Independent Samples T Test..."
+msgstr "Prova T per a Mostres _Independents..."
 
-#: src/ui/gui/data-editor.ui:368
-msgid "_Paired Samples T Test"
-msgstr "Prova T per mostres A_parellades"
+#: src/ui/gui/data-editor.ui:379
+msgid "_Paired Samples T Test..."
+msgstr "Prova T per a Mostres A_parellades..."
 
-#: src/ui/gui/data-editor.ui:374
-msgid "One Way _ANOVA"
-msgstr "_ANOVA d'un factor"
+#: src/ui/gui/data-editor.ui:385
+msgid "One Way _ANOVA..."
+msgstr "_ANOVA d'un factor..."
 
-#: src/ui/gui/data-editor.ui:380
+#: src/ui/gui/data-editor.ui:391
 msgid "Bivariate _Correlation..."
 msgstr "_Correlació Bivariada..."
 
-#: src/ui/gui/data-editor.ui:386
-msgid "Factor _Analysis"
-msgstr "_Anàlisi Factorial"
+#: src/ui/gui/data-editor.ui:397
+msgid "Factor _Analysis..."
+msgstr "_Anàlisi Factorial..."
 
-#: src/ui/gui/data-editor.ui:392
-msgid "Re_liability"
-msgstr "Fiabi_litat"
+#: src/ui/gui/data-editor.ui:403
+msgid "Re_liability..."
+msgstr "Fiabi_litat..."
 
-#: src/ui/gui/data-editor.ui:398
-msgid "Linear _Regression"
-msgstr "_Regressió Linear"
+#: src/ui/gui/data-editor.ui:409
+msgid "Linear _Regression..."
+msgstr "_Regressió Lineal..."
 
-#: src/ui/gui/data-editor.ui:404
+#: src/ui/gui/data-editor.ui:415
 msgid "_Non-Parametric Statistics"
 msgstr "Proves _No-Paramétriques"
 
-#: src/ui/gui/data-editor.ui:410
-msgid "_Chi-Square"
-msgstr "_Chi-quadrat"
+#: src/ui/gui/data-editor.ui:421
+msgid "_Chi-Square..."
+msgstr "_Chi-quadrat..."
 
-#: src/ui/gui/data-editor.ui:416
-msgid "_Binomial"
-msgstr "_Binomial"
+#: src/ui/gui/data-editor.ui:427
+msgid "_Binomial..."
+msgstr "_Binomial..."
 
-#: src/ui/gui/data-editor.ui:422
-msgid "K Related _Samples"
-msgstr "K mostres aparellades"
+#: src/ui/gui/data-editor.ui:433
+msgid "K Related _Samples..."
+msgstr "K Mostre_s aparellades..."
 
-#: src/ui/gui/data-editor.ui:428
+#: src/ui/gui/data-editor.ui:439
 msgid "ROC Cur_ve..."
 msgstr "Corba ROC..."
 
-#: src/ui/gui/data-editor.ui:434
+#: src/ui/gui/data-editor.ui:445
 msgid "_Utilities"
 msgstr "_Utilitats"
 
-#: src/ui/gui/data-editor.ui:441
+#: src/ui/gui/data-editor.ui:451
+msgid "_Variables..."
+msgstr "_Variables..."
+
+#: src/ui/gui/data-editor.ui:452
 msgid "Jump to variable"
 msgstr "Anar a la variable"
 
-#: src/ui/gui/data-editor.ui:448
-msgid "Data File _Comments"
-msgstr "_Comentaris arxiu de dades"
+#: src/ui/gui/data-editor.ui:459
+msgid "Data File _Comments..."
+msgstr "_Comentaris arxiu de dades..."
 
-#: src/ui/gui/data-editor.ui:454 src/ui/gui/output-viewer.ui:46
-#: src/ui/gui/syntax-editor.ui:135
+#: src/ui/gui/data-editor.ui:465 src/ui/gui/output-viewer.ui:47
+#: src/ui/gui/syntax-editor.ui:125
 msgid "_Windows"
 msgstr "Finestres"
 
-#: src/ui/gui/data-editor.ui:460 src/ui/gui/output-viewer.ui:52
-#: src/ui/gui/syntax-editor.ui:141
+#: src/ui/gui/data-editor.ui:471 src/ui/gui/output-viewer.ui:53
+#: src/ui/gui/syntax-editor.ui:131
 msgid "_Minimize All Windows"
 msgstr "_Minimitza totes les finestres"
 
-#: src/ui/gui/data-editor.ui:466
+#: src/ui/gui/data-editor.ui:477
 msgid "_Split"
 msgstr "Divideix"
 
-#: src/ui/gui/data-editor.ui:642
+#: src/ui/gui/data-editor.ui:654
 msgid "Information Area"
 msgstr "Àrea d'Informació"
 
-#: src/ui/gui/data-editor.ui:664
+#: src/ui/gui/data-editor.ui:676
 msgid "Processor Area"
 msgstr "Area del processador"
 
-#: src/ui/gui/data-editor.ui:689
+#: src/ui/gui/data-editor.ui:701
 msgid "Case Counter Area"
 msgstr "Area del Recompte"
 
-#: src/ui/gui/data-editor.ui:714
+#: src/ui/gui/data-editor.ui:726
 msgid "Filter Use Status Area"
 msgstr "Area del Filtre"
 
-#: src/ui/gui/data-editor.ui:740
+#: src/ui/gui/data-editor.ui:752
 msgid "Weight Status Area"
 msgstr "Area de Ponderació"
 
-#: src/ui/gui/data-editor.ui:766
+#: src/ui/gui/data-editor.ui:778
 msgid "Split File Status Area"
 msgstr "Area de Divisió"
 
-#: src/ui/gui/output-viewer.ui:22
-msgid "_Export"
-msgstr "_Exportar"
+#: src/ui/gui/output-viewer.ui:16
+msgid "_Print..."
+msgstr "Im_primir..."
+
+#: src/ui/gui/output-viewer.ui:23
+msgid "_Export..."
+msgstr "_Exportar..."
 
-#: src/ui/gui/syntax-editor.ui:104
+#: src/ui/gui/syntax-editor.ui:94
 msgid "_Run"
 msgstr "Executa_r"
 
-#: src/ui/gui/syntax-editor.ui:110
+#: src/ui/gui/syntax-editor.ui:100
 msgid "All"
 msgstr "Tots"
 
-#: src/ui/gui/syntax-editor.ui:116
+#: src/ui/gui/syntax-editor.ui:106
 msgid "Selection"
 msgstr "Selecció"
 
-#: src/ui/gui/syntax-editor.ui:122
+#: src/ui/gui/syntax-editor.ui:112
 msgid "Current Line"
 msgstr "Linia actual"
 
-#: src/ui/gui/syntax-editor.ui:129
+#: src/ui/gui/syntax-editor.ui:119
 msgid "To End"
 msgstr "Fins al final"
 
+#~ msgid "Scratch file handle %s has not yet been written, using SAVE or another procedure, so it cannot yet be used for reading."
+#~ msgstr "El manipulador de l'arxius de treball %s encara no s'ha escrit, utilitzant SAVE o altre procediment, de manera que encara no es pot llegir."
+
+#~ msgid "scratch file"
+#~ msgstr "arxiu de treball"
+
+#~ msgid "Variable suffix too large."
+#~ msgstr "Sufix de la variable massa gran."
+
+#~ msgid "Missing space following `%c' at UTF-8 offset %zu in MRSETS record."
+#~ msgstr "Espai perdut darrera `%c' a la posició UTF-8 %zu d'un registre MRSETS."
+
+#~ msgid "Unexpected label source value `%s' following `E' at UTF-8 offset %zu in MRSETS record."
+#~ msgstr "Valor d'etiqueta no esperat `%s' darrera `E' a la posició UTF-8 %zu d'un registre MRSETS."
+
+#~ msgid "PSPP-data"
+#~ msgstr "datos-PSPP"
+
+#~ msgid "Syntax"
+#~ msgstr "Sintaxi"
+
+#~ msgid "%s %s PSPPIRE %s"
+#~ msgstr "%s %s PSPPIRE %s"
+
+#~ msgid "Untitled"
+#~ msgstr "Sense titol"
+
 #~ msgid "Cannot create variable name from %s"
 #~ msgstr "No es pot crear el nom de la variable des de %s"
 
@@ -7352,9 +7454,6 @@ msgstr "Fins al final"
 #~ msgid "Sort Descending"
 #~ msgstr "Ordenació descendent"
 
-#~ msgid "_Fonts"
-#~ msgstr "_Fonts"
-
 #~ msgid "Buttons"
 #~ msgstr "Botons"
 
@@ -7794,9 +7893,6 @@ msgstr "Fins al final"
 #~ msgid "_About"
 #~ msgstr "Qu_ant a..."
 
-#~ msgid "Print"
-#~ msgstr "Iimprimir"
-
 #~ msgid "Recall"
 #~ msgstr "Refer"
 
@@ -7806,9 +7902,6 @@ msgstr "Fins al final"
 #~ msgid "Redo"
 #~ msgstr "Re-Fer"
 
-#~ msgid "Find"
-#~ msgstr "Cercar"
-
 #~ msgid "Use Sets"
 #~ msgstr "Utilitzar conjunts"
 
index a7ff31ba0b36e68ab477e1153686117ab88d5a08..0fb1e8576e39d29cd107c866879a1ebd2f3053ae 100644 (file)
--- a/po/es.po
+++ b/po/es.po
@@ -6,12 +6,13 @@
 # Javier Gómez Serrano, 2009.
 # Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>, 2010.
 # Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>, 2011.
+# Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>, 2011.
 msgid ""
 msgstr ""
-"Project-Id-Version: pspp-0.7.7\n"
+"Project-Id-Version: pspp-0.7.8\n"
 "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
-"POT-Creation-Date: 2011-03-24 20:36-0700\n"
-"PO-Revision-Date: 2011-05-03 01:49+0200\n"
+"POT-Creation-Date: 2011-05-04 06:57-0700\n"
+"PO-Revision-Date: 2011-08-17 13:28+0200\n"
 "Last-Translator: Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>\n"
 "Language-Team: Spanish <es@li.org>\n"
 "Language: es\n"
@@ -24,38 +25,38 @@ msgstr ""
 msgid "Sorry. The help system hasn't yet been implemented."
 msgstr "Disculpas. El sistema de ayuda todavía no ha sido implementado."
 
-#: src/ui/gui/psppire-buttonbox.c:275 src/ui/gui/psppire-buttonbox.c:437
+#: src/ui/gui/psppire-buttonbox.c:313 src/ui/gui/psppire-buttonbox.c:469
 msgid "Continue"
 msgstr "Continuar"
 
-#: src/ui/gui/psppire-buttonbox.c:435
+#: src/ui/gui/psppire-buttonbox.c:467
 msgid "OK"
 msgstr "Ok"
 
-#: src/ui/gui/psppire-buttonbox.c:436
+#: src/ui/gui/psppire-buttonbox.c:468
 msgid "Go To"
 msgstr "Ir a"
 
-#: src/ui/gui/psppire-buttonbox.c:438
+#: src/ui/gui/psppire-buttonbox.c:470
 msgid "Cancel"
 msgstr "Cancelar"
 
-#: src/ui/gui/psppire-buttonbox.c:439
+#: src/ui/gui/psppire-buttonbox.c:471
 msgid "Help"
 msgstr "Ayuda"
 
-#: src/ui/gui/psppire-buttonbox.c:440
+#: src/ui/gui/psppire-buttonbox.c:472
 msgid "Reset"
 msgstr "Reiniciar"
 
-#: src/ui/gui/psppire-buttonbox.c:441
+#: src/ui/gui/psppire-buttonbox.c:473
 msgid "Paste"
 msgstr "Pegar"
 
 #: src/ui/gui/psppire-dictview.c:466 src/language/dictionary/split-file.c:82
 #: src/language/dictionary/sys-file-info.c:149
-#: src/language/dictionary/sys-file-info.c:334
-#: src/language/dictionary/sys-file-info.c:658
+#: src/language/dictionary/sys-file-info.c:332
+#: src/language/dictionary/sys-file-info.c:646
 #: src/language/stats/descriptives.c:895
 #: src/language/data-io/data-parser.c:683
 #: src/language/data-io/data-parser.c:722 src/language/data-io/print.c:403
@@ -66,7 +67,7 @@ msgstr "Variable"
 msgid "Prefer variable labels"
 msgstr "Prefiero las etiquetas de variable"
 
-#: src/ui/gui/psppire-var-view.c:193
+#: src/ui/gui/psppire-var-view.c:192
 #, c-format
 msgid "Var%d"
 msgstr "Var%d"
@@ -110,7 +111,7 @@ msgstr "Al menos un caso en la lectura de datos tenia un valor de ponderación q
 msgid "CSV file"
 msgstr "archivo CSV"
 
-#: src/data/csv-file-writer.c:163 src/data/sys-file-writer.c:219
+#: src/data/csv-file-writer.c:163 src/data/sys-file-writer.c:225
 #, c-format
 msgid "Error opening `%s' for writing as a system file: %s."
 msgstr "Error al abrir `%s' para grabar como archivo de sistema: %s."
@@ -243,6 +244,17 @@ msgstr "Número del día de la semana %f no está entre 1 y 7."
 msgid "Month number %f is not between 1 and 12."
 msgstr "Número del mes %f no está entre 1 y 12."
 
+#: src/data/dataset-reader.c:54
+#, c-format
+msgid "Cannot read from dataset %s because no dictionary or data has been written to it yet."
+msgstr "No es pot llegir de l'arxiu de dades actiu %s perquè no s'ha omplert encara amb cap diccionari o dades."
+
+#. TRANSLATORS: this fragment will be interpolated into
+#. messages in fh_lock() that identify types of files.
+#: src/data/dataset-writer.c:66 src/language/data-io/file-handle.q:182
+msgid "dataset"
+msgstr "archivo de datos"
+
 #: src/data/dict-class.c:52
 msgid "ordinary"
 msgstr "ordinaria"
@@ -255,26 +267,30 @@ msgstr "sistema"
 msgid "scratch"
 msgstr "borrador"
 
-#: src/data/dictionary.c:1007
+#: src/data/dictionary.c:1003
 msgid "At least one case in the data file had a weight value that was user-missing, system-missing, zero, or negative.  These case(s) were ignored."
 msgstr "Al menos un caso del archivo de datos tenía un valor de ponderación perdido de usuario, de sistema, cero o negativo. Estos caso(s) fueron ignorado(s)."
 
-#: src/data/dictionary.c:1333
+#: src/data/dictionary.c:1329
 #, c-format
 msgid "Truncating document line to %d bytes."
 msgstr "Linea de documento truncada a  %d bytes."
 
-#: src/data/file-handle-def.c:469
+#: src/data/file-handle-def.c:254
+msgid "active dataset"
+msgstr "archivo de datos activo"
+
+#: src/data/file-handle-def.c:465
 #, c-format
 msgid "Can't read from %s as a %s because it is already being read as a %s."
 msgstr "No se puede leer de %s como una %s porque ya esta siendo leída como una %s."
 
-#: src/data/file-handle-def.c:473
+#: src/data/file-handle-def.c:469
 #, c-format
 msgid "Can't write to %s as a %s because it is already being written as a %s."
 msgstr "No se puede escribir en %s como una %s porque ya esta siendo escrita como una %s."
 
-#: src/data/file-handle-def.c:480
+#: src/data/file-handle-def.c:476
 #, c-format
 msgid "Can't re-open %s as a %s."
 msgstr "No se puede re-abrir %s como %s."
@@ -334,19 +350,19 @@ msgid "%s variables are not compatible with %s format %s."
 msgstr "Las variables %s no son compatibles con %s formato %s."
 
 #: src/data/format.c:412 src/data/sys-file-reader.c:1078
-#: src/ui/gui/psppire-var-store.c:629 src/ui/gui/compute.ui:503
+#: src/ui/gui/psppire-var-store.c:628 src/ui/gui/compute.ui:503
 #: src/ui/gui/var-sheet-dialogs.ui:139
 msgid "String"
 msgstr "Cadena"
 
 #: src/data/format.c:412 src/data/sys-file-reader.c:1078
-#: src/ui/gui/psppire-var-store.c:622 src/ui/gui/compute.ui:584
+#: src/ui/gui/psppire-var-store.c:621 src/ui/gui/compute.ui:584
 #: src/ui/gui/var-sheet-dialogs.ui:27
 msgid "Numeric"
 msgstr "Numérico"
 
-#: src/data/format.c:413 src/data/sys-file-reader.c:1663
-#: src/data/sys-file-reader.c:1665 src/language/xforms/recode.c:506
+#: src/data/format.c:413 src/data/sys-file-reader.c:1671
+#: src/data/sys-file-reader.c:1673 src/language/xforms/recode.c:506
 #: src/language/xforms/recode.c:507 src/language/xforms/recode.c:519
 #: src/language/xforms/recode.c:520
 #: src/language/dictionary/apply-dictionary.c:77
@@ -354,8 +370,8 @@ msgstr "Numérico"
 msgid "numeric"
 msgstr "numérico"
 
-#: src/data/format.c:413 src/data/sys-file-reader.c:1663
-#: src/data/sys-file-reader.c:1665 src/language/xforms/recode.c:506
+#: src/data/format.c:413 src/data/sys-file-reader.c:1671
+#: src/data/sys-file-reader.c:1673 src/language/xforms/recode.c:506
 #: src/language/xforms/recode.c:507 src/language/xforms/recode.c:519
 #: src/language/xforms/recode.c:520
 #: src/language/dictionary/apply-dictionary.c:77
@@ -382,7 +398,7 @@ msgstr "Error al abrir `%s' para la lectura como archivo Gnumeric: %s."
 msgid "Invalid cell range `%s'"
 msgstr "Intervalo de celda `%s' inválido"
 
-#: src/data/gnumeric-reader.c:522
+#: src/data/gnumeric-reader.c:521
 #, c-format
 msgid "Selected sheet or range of spreadsheet `%s' is empty."
 msgstr "La hoja o el intervalo de hojas de cálculo seleccionadas `%s' está vacía."
@@ -456,141 +472,141 @@ msgstr "Eliminando %s: %s."
 msgid "%s is not a valid name for a multiple response set.  Multiple response set names must begin with `$'."
 msgstr "%s no es un nombre válido de variable para un conjunto de respuesta múltiple. Los conjuntos de respuesta múltiple han de comenzar con `$'."
 
-#: src/data/por-file-reader.c:100
+#: src/data/por-file-reader.c:101
 #, c-format
 msgid "portable file %s corrupt at offset 0x%llx: "
 msgstr "el archivo portátil %s está corrupto en la posición 0x%llx: "
 
-#: src/data/por-file-reader.c:132
+#: src/data/por-file-reader.c:133
 #, c-format
 msgid "reading portable file %s at offset 0x%llx: "
 msgstr "leyendo el archivo portátil %s en la posición 0x%llx: "
 
-#: src/data/por-file-reader.c:163
+#: src/data/por-file-reader.c:164
 #, c-format
 msgid "Error closing portable file `%s': %s."
 msgstr "Error cerrando el archivo portátil `%s': %s."
 
-#: src/data/por-file-reader.c:215
+#: src/data/por-file-reader.c:216
 msgid "unexpected end of file"
 msgstr "fin de archivo inesperado"
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
-#: src/data/por-file-reader.c:274 src/data/por-file-writer.c:148
+#: src/data/por-file-reader.c:275 src/data/por-file-writer.c:148
 msgid "portable file"
 msgstr "archivo portátil"
 
-#: src/data/por-file-reader.c:282
+#: src/data/por-file-reader.c:283
 #, c-format
 msgid "An error occurred while opening `%s' for reading as a portable file: %s."
 msgstr "Error abriendo `%s' para la lectura como archivo portátil: %s."
 
-#: src/data/por-file-reader.c:303
+#: src/data/por-file-reader.c:304
 msgid "Data record expected."
 msgstr "Registro de datos esperado."
 
-#: src/data/por-file-reader.c:385
+#: src/data/por-file-reader.c:386
 msgid "Number expected."
 msgstr "Número esperado."
 
-#: src/data/por-file-reader.c:413
+#: src/data/por-file-reader.c:414
 msgid "Missing numeric terminator."
 msgstr "Falta la terminación numérica."
 
-#: src/data/por-file-reader.c:436
+#: src/data/por-file-reader.c:437
 msgid "Invalid integer."
 msgstr "Número entero inválido."
 
-#: src/data/por-file-reader.c:447 src/data/por-file-reader.c:467
+#: src/data/por-file-reader.c:448 src/data/por-file-reader.c:468
 #, c-format
 msgid "Bad string length %d."
 msgstr "Longitud de cadena %d inválida."
 
-#: src/data/por-file-reader.c:530
+#: src/data/por-file-reader.c:531
 #, c-format
 msgid "%s: Not a portable file."
 msgstr "%s: No es un archivo portátil."
 
-#: src/data/por-file-reader.c:547
+#: src/data/por-file-reader.c:548
 #, c-format
 msgid "Unrecognized version code `%c'."
 msgstr "Código de versión no reconocido `%c'."
 
-#: src/data/por-file-reader.c:556
+#: src/data/por-file-reader.c:557
 #, c-format
 msgid "Bad date string length %zu."
 msgstr "Longitud de cadena de datos %zu inválida."
 
-#: src/data/por-file-reader.c:558
+#: src/data/por-file-reader.c:559
 #, c-format
 msgid "Bad time string length %zu."
 msgstr "Longitud de cadena de tiempo %zu inválida."
 
-#: src/data/por-file-reader.c:600
+#: src/data/por-file-reader.c:601
 #, c-format
 msgid "%s: Bad format specifier byte (%d).  Variable will be assigned a default format."
 msgstr "%s: Byte especificador de formato inválido (%d). Se asignará formato predeterminado a la variable."
 
-#: src/data/por-file-reader.c:621
+#: src/data/por-file-reader.c:622
 #, c-format
 msgid "Numeric variable %s has invalid format specifier %s."
 msgstr "La variable numérica %s tiene una especificación de formato inválida %s."
 
-#: src/data/por-file-reader.c:625
+#: src/data/por-file-reader.c:626
 #, c-format
 msgid "String variable %s with width %d has invalid format specifier %s."
 msgstr "La variable en cadena %s con longitud %d tiene una especificación de formato inválida %s."
 
-#: src/data/por-file-reader.c:649
+#: src/data/por-file-reader.c:650
 msgid "Expected variable count record."
 msgstr "Registro de recuento de variables esperado."
 
-#: src/data/por-file-reader.c:653
+#: src/data/por-file-reader.c:654
 #, c-format
 msgid "Invalid number of variables %d."
 msgstr "Número inválido de variables: %d."
 
-#: src/data/por-file-reader.c:662
+#: src/data/por-file-reader.c:663
 #, c-format
 msgid "Weight variable name (%s) truncated."
 msgstr "Nombre de la variable ponderada (%s) truncado."
 
-#: src/data/por-file-reader.c:677
+#: src/data/por-file-reader.c:678
 msgid "Expected variable record."
 msgstr "Registro de variable esperado."
 
-#: src/data/por-file-reader.c:681
+#: src/data/por-file-reader.c:682
 #, c-format
 msgid "Invalid variable width %d."
 msgstr "Ancho de variable inválida %d."
 
-#: src/data/por-file-reader.c:689
+#: src/data/por-file-reader.c:690
 #, c-format
 msgid "Invalid variable name `%s' in position %d."
 msgstr "Nombre de la variable inválido `%s' en la posición %d."
 
-#: src/data/por-file-reader.c:693 src/data/sys-file-reader.c:963
+#: src/data/por-file-reader.c:694 src/data/sys-file-reader.c:963
 #, c-format
 msgid "Bad width %d for variable %s."
 msgstr "Ancho %d incorrecto para la variable %s."
 
-#: src/data/por-file-reader.c:707
+#: src/data/por-file-reader.c:708
 #, c-format
 msgid "Duplicate variable name %s in position %d renamed to %s."
 msgstr "Nombre de la variable %s duplicado en la posición %d se ha renombrado a %s."
 
-#: src/data/por-file-reader.c:756
+#: src/data/por-file-reader.c:757
 #, c-format
 msgid "Weighting variable %s not present in dictionary."
 msgstr "La variable de ponderación %s no está en el diccionario."
 
-#: src/data/por-file-reader.c:800
+#: src/data/por-file-reader.c:801
 #, c-format
 msgid "Unknown variable %s while parsing value labels."
 msgstr "Variable %s desconocida mientras se analizaban las etiquetas de valor."
 
-#: src/data/por-file-reader.c:803
+#: src/data/por-file-reader.c:804
 #, c-format
 msgid "Cannot assign value labels to %s and %s, which have different variable types."
 msgstr "No se puede asignar etiquetas de valor a %s y %s, que tienen diferentes tipos de variables."
@@ -610,25 +626,25 @@ msgstr "Error abriendo `%s' para escribir como archivo portátil: %s."
 msgid "An I/O error occurred writing portable file `%s'."
 msgstr "Error I/O al escribir el archivo portátil `%s'."
 
-#: src/data/psql-reader.c:46
+#: src/data/psql-reader.c:47
 msgid "Support for reading postgres databases was not compiled into this installation of PSPP"
 msgstr "El soporte para la lectura de las bases de datos postgres no fue compilado en esta instalación de PSPP"
 
-#: src/data/psql-reader.c:239
+#: src/data/psql-reader.c:241
 msgid "Memory error whilst opening psql source"
 msgstr "Error de memoria en abrir la fuente psql"
 
-#: src/data/psql-reader.c:245
+#: src/data/psql-reader.c:247
 #, c-format
 msgid "Error opening psql source: %s."
 msgstr "Error abriendo la fuente psql: %s."
 
-#: src/data/psql-reader.c:260
+#: src/data/psql-reader.c:262
 #, c-format
 msgid "Postgres server is version %s. Reading from versions earlier than 8.0 is not supported."
 msgstr "La versión del servidor Postgres es la %s. No es posible la lectura desde versiones anteriores a la 8.0."
 
-#: src/data/psql-reader.c:280
+#: src/data/psql-reader.c:282
 msgid "Connection is unencrypted, but unencrypted connections have not been permitted."
 msgstr "La conexión no está cifrada, pero las conexiones sin cifrar no están permitidas."
 
@@ -643,17 +659,6 @@ msgstr "Error desde la fuente psql: %s."
 msgid "Unsupported OID %d.  SYSMIS values will be inserted."
 msgstr "OID %d no admitido. Valores SYSMIS serán insertados."
 
-#: src/data/scratch-reader.c:54
-#, c-format
-msgid "Scratch file handle %s has not yet been written, using SAVE or another procedure, so it cannot yet be used for reading."
-msgstr "El manipulador de archivos de trabajo %s aún no se ha escrito, utilizando SAVE u otro procedimiento, de forma que aún no se puede leer."
-
-#. TRANSLATORS: this fragment will be interpolated into
-#. messages in fh_lock() that identify types of files.
-#: src/data/scratch-writer.c:66 src/language/data-io/file-handle.q:186
-msgid "scratch file"
-msgstr "archivo de trabajo"
-
 #: src/data/settings.c:384
 msgid "MXWARNS set to zero.  No further warnings will be given even when potentially problematic situations are encountered."
 msgstr "MXWARNS colocado a cero.  NIngún aviso se mostrará en lo sucesivo aunque se den situaciones problemáticas."
@@ -668,40 +673,36 @@ msgstr "Avisos re-activados. %d avisos se mostraran antes de abortar el procesam
 msgid "%s: Custom currency string `%s' does not contain exactly three periods or commas (or it contains both)."
 msgstr "%s: La cadena de moneda personalizada '%s' no contiene exactamente tres puntos o comas (o contiene ambos)."
 
-#: src/data/short-names.c:52
-msgid "Variable suffix too large."
-msgstr "Sufijo de la variable demasiado grande."
-
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
-#: src/data/sys-file-reader.c:323 src/data/sys-file-writer.c:207
+#: src/data/sys-file-reader.c:324 src/data/sys-file-writer.c:213
 msgid "system file"
 msgstr "archivo de sistema"
 
-#: src/data/sys-file-reader.c:330
+#: src/data/sys-file-reader.c:331
 #, c-format
 msgid "Error opening `%s' for reading as a system file: %s."
 msgstr "Error abriendo `%s' para la lectura como archivo de sistema: %s."
 
-#: src/data/sys-file-reader.c:387 tests/dissect-sysfile.c:155
+#: src/data/sys-file-reader.c:388 tests/dissect-sysfile.c:155
 msgid "Misplaced type 4 record."
 msgstr "Registro de tipo 4 fuera de lugar."
 
-#: src/data/sys-file-reader.c:391
+#: src/data/sys-file-reader.c:392
 msgid "Duplicate type 6 (document) record."
 msgstr "Registros de tipo 6 (document) duplicados."
 
-#: src/data/sys-file-reader.c:400 src/data/sys-file-reader.c:900
+#: src/data/sys-file-reader.c:401 src/data/sys-file-reader.c:900
 #, c-format
 msgid "Unrecognized record type 7, subtype %d.  Please send a copy of this file, and the syntax which created it to %s."
 msgstr "Registro de tipo 7, subtipo %d , no reconocido. Por favor envíe una copia de este archivo, así como de la sintaxis que lo creó a %s."
 
-#: src/data/sys-file-reader.c:409
+#: src/data/sys-file-reader.c:410
 #, c-format
 msgid "Record type 7, subtype %d found here has the same type as the record found near offset 0x%llx.  Please send a copy of this file, and the syntax which created it to %s."
 msgstr "Registro de tipo 7, subtipo %d encontrado aquí del mismo tipo que el registro encontrado cerca de la posición 0x%llx. Por favor envíe una copia de este archivo y de la sintaxis que lo creó a %s."
 
-#: src/data/sys-file-reader.c:422 tests/dissect-sysfile.c:166
+#: src/data/sys-file-reader.c:423 tests/dissect-sysfile.c:166
 #, c-format
 msgid "Unrecognized record type %d."
 msgstr "Tipo de registro %d no reconocido."
@@ -713,8 +714,8 @@ msgstr "Variable de ponderación tiene que ser numérica (no cadena textual `%s'
 
 #: src/data/sys-file-reader.c:502
 #, c-format
-msgid "File header claims %d variable positions but %d were read from file."
-msgstr "Cabecera del archivo requiere %d posiciones de variable, per se han leído %d desde el archivo."
+msgid "File header claims %d variable positions but %zu were read from file."
+msgstr "La cabecera del archivo requiere %d posiciones de variable, pero se han leído %zu desde el archivo."
 
 #: src/data/sys-file-reader.c:542
 #, c-format
@@ -753,8 +754,8 @@ msgstr "Registro de índice de variable (tipo 4) no está seguido inmediatament,
 
 #: src/data/sys-file-reader.c:782
 #, c-format
-msgid "Number of variables associated with a value label (%d) is not between 1 and the number of variables (%zu)."
-msgstr "Número de variables asociadas con una etiqueta de valores (%d) no está entre 1 y el número de variables (%zu)."
+msgid "Number of variables associated with a value label (%zu) is not between 1 and the number of variables (%zu)."
+msgstr "El número de variables asociadas con una etiqueta de valor (%zu) no está entre 1 y el número de variables (%zu)."
 
 #: src/data/sys-file-reader.c:803
 #, c-format
@@ -826,321 +827,321 @@ msgstr "El archivo especifica un valor inesperado %g como %s."
 
 #: src/data/sys-file-reader.c:1252
 #, c-format
-msgid "`%s' does not begin with `$' at UTF-8 offset %zu in MRSETS record."
-msgstr "`%s' no comienza con `$' en la posición UTF-8 %zu de un registro MRSETS."
+msgid "`%s' does not begin with `$' at offset %zu in MRSETS record."
+msgstr "`%s' no comienza con `$' en la posición %zu de un registro MRSETS."
 
 #: src/data/sys-file-reader.c:1263 src/data/sys-file-reader.c:1282
 #, c-format
-msgid "Missing space following `%c' at UTF-8 offset %zu in MRSETS record."
-msgstr "Espacio perdido tras `%c' en la posición UTF-8 %zu del registro MRSETS."
+msgid "Missing space following `%c' at offset %zu in MRSETS record."
+msgstr "Espacio perdido tras `%c' en la posición %zu de un registro MRSETS."
 
 #: src/data/sys-file-reader.c:1292
 #, c-format
-msgid "Unexpected label source value `%s' following `E' at UTF-8 offset %zu in MRSETS record."
-msgstr "Etiqueta de valor fuente inesperada `%s' tras 'E' en la posición UTF-8 %zu del registro MRSETS."
+msgid "Unexpected label source value `%s' following `E' at offset %zu in MRSETS record."
+msgstr "Valor de etiqueta inesperado `%s' tras `E' en la posición %zu de un registro MRSETS."
 
 #: src/data/sys-file-reader.c:1299
 #, c-format
-msgid "Missing `C', `D', or `E' at UTF-8 offset %zu in MRSETS record."
-msgstr "Falta `C', `D' o `E' en la posición UTF-8 %zu del registro MRSETS."
+msgid "Missing `C', `D', or `E' at offset %zu in MRSETS record."
+msgstr "Falta `C', `D' o `E' en la posición %zu de un registro MRSETS."
 
-#: src/data/sys-file-reader.c:1329
+#: src/data/sys-file-reader.c:1331
 #, c-format
-msgid "Missing new-line parsing variable names at UTF-8 offset %zu in MRSETS record."
-msgstr "Faltan nombres de variables de la nueva línea en la posición UTF-8 %zu del registro MRSETS."
+msgid "Missing new-line parsing variable names at offset %zu in MRSETS record."
+msgstr "Faltan nombres de variables para nueva línea en la posición %zu de un registro MRSETS."
 
-#: src/data/sys-file-reader.c:1341
+#: src/data/sys-file-reader.c:1347
 #, c-format
-msgid "Duplicate variable name %s at UTF-8 offset %zu in MRSETS record."
-msgstr "Nombre de la variable %s duplicado en la posición UTF-8 %zu en registro MRSETS."
+msgid "Duplicate variable name %s at offset %zu in MRSETS record."
+msgstr "Nombre de variable %s duplicado en la posición %zu de un registro MRSETS."
 
-#: src/data/sys-file-reader.c:1355
+#: src/data/sys-file-reader.c:1363
 #, c-format
 msgid "MRSET %s contains both string and numeric variables."
 msgstr "MRSET %s contiene tanto variables textuales como numéricas."
 
-#: src/data/sys-file-reader.c:1371
+#: src/data/sys-file-reader.c:1379
 #, c-format
 msgid "MRSET %s has only %zu variables."
 msgstr "MRSET %s tiene sólo %zu variables."
 
-#: src/data/sys-file-reader.c:1417 tests/dissect-sysfile.c:771
+#: src/data/sys-file-reader.c:1425 tests/dissect-sysfile.c:771
 #, c-format
 msgid "Extension 11 has bad count %zu (for %zu variables)."
 msgstr "Extensión 11 tiene un recuento inválido %zu (para %zu variables)."
 
-#: src/data/sys-file-reader.c:1451
+#: src/data/sys-file-reader.c:1459
 #, c-format
 msgid "Invalid variable display parameters for variable %zu (%s).  Default parameters substituted."
 msgstr "Parámetros de visualización de variable no válidos para la variable %zu (%s). Sustitución de parámetros por defecto."
 
-#: src/data/sys-file-reader.c:1548
+#: src/data/sys-file-reader.c:1556
 #, c-format
 msgid "Long variable mapping from %s to invalid variable name `%s'."
 msgstr "Identificación de variable larga desde %s hacia un nombre de variable inválido '%s'."
 
-#: src/data/sys-file-reader.c:1559
+#: src/data/sys-file-reader.c:1567
 #, c-format
 msgid "Duplicate long variable name `%s'."
 msgstr "Nombre largo de la variable `%s' duplicado."
 
-#: src/data/sys-file-reader.c:1592
+#: src/data/sys-file-reader.c:1600
 #, c-format
 msgid "%s listed as string of invalid length %s in very long string record."
 msgstr "%s figura como cadena de longitud no válida %s en un registro de cadena muy largo."
 
-#: src/data/sys-file-reader.c:1603
+#: src/data/sys-file-reader.c:1611
 #, c-format
 msgid "%s listed in very long string record with width %s, which requires only one segment."
 msgstr "%s figura en el registro de cadena muy larga con longitud %s, que requiere solo un segmento."
 
-#: src/data/sys-file-reader.c:1610
+#: src/data/sys-file-reader.c:1618
 #, c-format
 msgid "Very long string %s overflows dictionary."
 msgstr "Cadena muy larga %s desborda el diccionario."
 
-#: src/data/sys-file-reader.c:1625
+#: src/data/sys-file-reader.c:1633
 #, c-format
 msgid "Very long string with width %ld has segment %d of width %d (expected %d)."
 msgstr "Cadena muy larga con una longitud %ld tiene un segmento %d de longitud %d (se espera %d)"
 
-#: src/data/sys-file-reader.c:1659
+#: src/data/sys-file-reader.c:1667
 #, c-format
 msgid "Variables associated with value label are not all of identical type.  Variable %s is %s, but variable %s is %s."
 msgstr "Las variables asociadas con etiqueta de valores no son todas del mismo tipo.  La variable %s es %s, pero la variable %s es %s."
 
-#: src/data/sys-file-reader.c:1676
+#: src/data/sys-file-reader.c:1684
 #, c-format
 msgid "Value labels may not be added to long string variables (e.g. %s) using records types 3 and 4."
 msgstr "No se pueden añadir etiquetas de valor a las variables de cadena larga (e.g. %s) utilizando los tipos de registro 3 y 4."
 
-#: src/data/sys-file-reader.c:1695
+#: src/data/sys-file-reader.c:1703
 #, c-format
 msgid "Duplicate value label for %g on %s."
 msgstr "Etiqueta de valor duplicad para %g en %s."
 
-#: src/data/sys-file-reader.c:1699 src/data/sys-file-reader.c:1941
+#: src/data/sys-file-reader.c:1707 src/data/sys-file-reader.c:1949
 #, c-format
 msgid "Duplicate value label for `%.*s' on %s."
 msgstr "Etiqueta de valor duplicada para `%.*s' en %s."
 
-#: src/data/sys-file-reader.c:1724
+#: src/data/sys-file-reader.c:1732
 #, c-format
-msgid "Variable index %d not in valid range 1...%d."
-msgstr "Índice de la variable %d no en el intervalo válido de 1...%d."
+msgid "Variable index %d not in valid range 1...%zu."
+msgstr "El índice de la variable %d no pertenece al intervalo válido 1...%zu."
 
-#: src/data/sys-file-reader.c:1733
+#: src/data/sys-file-reader.c:1741
 #, c-format
 msgid "Variable index %d refers to long string continuation."
 msgstr "Índice de la variable %d se refiere a una continuación de cadena larga."
 
-#: src/data/sys-file-reader.c:1769
+#: src/data/sys-file-reader.c:1777
 #, c-format
 msgid "Error parsing attribute value %s[%d]."
 msgstr "Error al analizar el valor del atributo %s[%d]"
 
-#: src/data/sys-file-reader.c:1783
+#: src/data/sys-file-reader.c:1791
 #, c-format
 msgid "Attribute value %s[%d] is not quoted: %s."
 msgstr "El valor del atributo %s[%d] no está entre comillas: %s."
 
-#: src/data/sys-file-reader.c:1836
+#: src/data/sys-file-reader.c:1844
 msgid "Long string value label record ends unexpectedly."
 msgstr "Etiqueta de valor de un registro de texto muy largo finaliza inesperadamente."
 
-#: src/data/sys-file-reader.c:1875
+#: src/data/sys-file-reader.c:1883
 #, c-format
 msgid "Ignoring long string value record for unknown variable %s."
 msgstr "Ignorando el registro del valor de cadena larga para la variable desconocida %s."
 
-#: src/data/sys-file-reader.c:1880
+#: src/data/sys-file-reader.c:1888
 #, c-format
 msgid "Ignoring long string value record for numeric variable %s."
 msgstr "Ignorando el registro del valor de cadena larga para la variable numérica %s."
 
-#: src/data/sys-file-reader.c:1887
+#: src/data/sys-file-reader.c:1895
 #, c-format
 msgid "Ignoring long string value record for variable %s because the record's width (%d) does not match the variable's width (%d)."
 msgstr "Ignorando el registro del valor de cadena larga %s ya que el ancho del registro (%d) no coincide con el ancho de la variable (%d)."
 
-#: src/data/sys-file-reader.c:1916
+#: src/data/sys-file-reader.c:1924
 #, c-format
 msgid "Ignoring long string value %zu for variable %s, with width %d, that has bad value width %zu."
 msgstr "Ignorando el valor de cadena larga %zu para la variable %s, de ancho %d, que tiene un ancho de valor incorrecto %zu."
 
-#: src/data/sys-file-reader.c:2020
+#: src/data/sys-file-reader.c:2028
 msgid "File ends in partial case."
 msgstr "El archivo acaba en un caso parcial."
 
-#: src/data/sys-file-reader.c:2028
+#: src/data/sys-file-reader.c:2036
 #, c-format
 msgid "Error reading case from file %s."
 msgstr "Error leyendo un caso del archivo %s."
 
-#: src/data/sys-file-reader.c:2130
+#: src/data/sys-file-reader.c:2138
 msgid "Possible compressed data corruption: compressed spaces appear in numeric field."
 msgstr "Posible corrupción de datos comprimidos: aparecen espacios comprimidos en un campo numérico."
 
-#: src/data/sys-file-reader.c:2184
+#: src/data/sys-file-reader.c:2192
 #, c-format
 msgid "Possible compressed data corruption: string contains compressed integer (opcode %d)."
 msgstr "Posible corrupción de datos comprimidos: una cadena textual contiene un entero comprimido (opcode %d)."
 
-#: src/data/sys-file-reader.c:2273
+#: src/data/sys-file-reader.c:2286
 #, c-format
 msgid "Suppressed %d additional related warnings."
 msgstr "Suprimidas %d advertencias adicionales."
 
-#: src/data/sys-file-reader.c:2318 src/data/sys-file-reader.c:2335
+#: src/data/sys-file-reader.c:2332 src/data/sys-file-reader.c:2349
 #, c-format
 msgid "Dictionary record refers to unknown variable %s."
 msgstr "El registro diccionario se refiere a una variable desconocida %s."
 
-#: src/data/sys-file-reader.c:2397
+#: src/data/sys-file-reader.c:2411
 #, c-format
-msgid "Expecting digit at UTF-8 offset %zu in MRSETS record."
-msgstr "Se espera un dígito en la posición UTF-8 %zu del registro MRSETS."
+msgid "Expecting digit at offset %zu in MRSETS record."
+msgstr "Se espera un dígito en la posición %zu de un registro MRSETS."
 
-#: src/data/sys-file-reader.c:2405
+#: src/data/sys-file-reader.c:2419
 #, c-format
-msgid "Expecting space at UTF-8 offset %zu in MRSETS record."
-msgstr "Se espera un espacio en la posición UTF-8 %zu del registre MRSETS."
+msgid "Expecting space at offset %zu in MRSETS record."
+msgstr "Se espera un espacio en la posición %zu de un registro MRSETS."
 
-#: src/data/sys-file-reader.c:2413
+#: src/data/sys-file-reader.c:2427
 #, c-format
-msgid "%zu-byte string starting at UTF-8 offset %zu exceeds record length %zu."
-msgstr "Un texto de %zu-bytes que comienza en la posición UTF-8 %zu excede la longitud del registro %zu. "
+msgid "%zu-byte string starting at offset %zu exceeds record length %zu."
+msgstr "Texto de %zu-bytes que comienza en la posición %zu excede la longitud del registro %zu. "
 
-#: src/data/sys-file-reader.c:2423
+#: src/data/sys-file-reader.c:2437
 #, c-format
-msgid "Expecting space at UTF-8 offset %zu following %zu-byte string."
-msgstr "Se espera un espacio en la posición UTF-8 %zu tras un texto de %zu-bytes."
+msgid "Expecting space at offset %zu following %zu-byte string."
+msgstr "Se espera un espacio en la posición %zu tras un texto de %zu-bytes."
 
-#: src/data/sys-file-reader.c:2465
+#: src/data/sys-file-reader.c:2478
 #, c-format
 msgid "`%s' near offset 0x%llx: "
 msgstr "`%s' cerca de la posición 0x%llx: "
 
-#: src/data/sys-file-reader.c:2468
+#: src/data/sys-file-reader.c:2481
 #, c-format
 msgid "`%s': "
 msgstr "`%s': "
 
-#: src/data/sys-file-reader.c:2525 tests/dissect-sysfile.c:1356
+#: src/data/sys-file-reader.c:2538 tests/dissect-sysfile.c:1356
 #, c-format
 msgid "System error: %s."
 msgstr "Error de sistema: %s."
 
-#: src/data/sys-file-reader.c:2527 tests/dissect-sysfile.c:1358
+#: src/data/sys-file-reader.c:2540 tests/dissect-sysfile.c:1358
 msgid "Unexpected end of file."
 msgstr "Final de archivo inesperado."
 
-#: src/data/sys-file-writer.c:180
+#: src/data/sys-file-writer.c:186
 #, c-format
 msgid "Unknown system file version %d. Treating as version %d."
 msgstr "Versión de archivo de sistema %d desconocida.Se tratará como versión %d."
 
-#: src/data/sys-file-writer.c:997
+#: src/data/sys-file-writer.c:1015
 #, c-format
 msgid "An I/O error occurred writing system file `%s'."
 msgstr "Error de E/S al guardar el archivo de sistema `%s'."
 
-#: src/data/variable.c:599
+#: src/data/variable.c:601
 #, c-format
 msgid "Truncating variable label for variable `%s' to %d bytes."
 msgstr "Truncando la etiqueta de la variable `%s' a %d bytes."
 
-#: src/language/command.c:193 src/language/expressions/parse.c:1294
+#: src/language/command.c:196 src/language/expressions/parse.c:1294
 #: src/language/utilities/set.q:196
 #, c-format
 msgid "%s is not yet implemented."
 msgstr "%s aún no está implementado."
 
-#: src/language/command.c:198
+#: src/language/command.c:201
 #, c-format
 msgid "%s may be used only in testing mode."
 msgstr "%s sólo puede ser utilizado en el modo de prueba."
 
-#: src/language/command.c:203
+#: src/language/command.c:206
 #, c-format
 msgid "%s may be used only in enhanced syntax mode."
 msgstr "%s sólo puede ser utilizado en modo de sintaxis ampliado."
 
-#: src/language/command.c:331
+#: src/language/command.c:334
 msgid "expecting command name"
 msgstr "esperando nombre de comando"
 
-#: src/language/command.c:333
+#: src/language/command.c:336
 #, c-format
 msgid "Unknown command `%s'."
 msgstr "Comando `%s' desconocido."
 
-#: src/language/command.c:366
+#: src/language/command.c:369
 #, c-format
 msgid "%s is allowed only before the active dataset has been defined."
 msgstr "%s sólo se permite antes de que el archivo de datos activo se haya definido."
 
-#: src/language/command.c:370
+#: src/language/command.c:373
 #, c-format
 msgid "%s is allowed only after the active dataset has been defined."
 msgstr "%s sólo se permite después que el archivo de datos activo se haya definido."
 
-#: src/language/command.c:374
+#: src/language/command.c:377
 #, c-format
 msgid "%s is allowed only inside INPUT PROGRAM."
 msgstr "%s sólo se permite dentro de INPUT PROGRAM."
 
-#: src/language/command.c:378
+#: src/language/command.c:381
 #, c-format
 msgid "%s is allowed only inside FILE TYPE."
 msgstr "%s sólo se permite dentro de FILE TYPE."
 
-#: src/language/command.c:385
+#: src/language/command.c:388
 #, c-format
 msgid "%s is allowed only before the active dataset has been defined or inside INPUT PROGRAM."
 msgstr "%s sólo se permite antes que el archivo de datos activo se haya definido o dentro de INPUT PROGRAM."
 
-#: src/language/command.c:389
+#: src/language/command.c:392
 #, c-format
 msgid "%s is allowed only before the active dataset has been defined or inside FILE TYPE."
 msgstr "%s sólo se permite antes que el archivo de datos activo se haya definido o dentro de FILE TYPE."
 
-#: src/language/command.c:393
+#: src/language/command.c:396
 #, c-format
 msgid "%s is allowed only after the active dataset has been defined or inside INPUT PROGRAM."
 msgstr "%s sólo se permite después que el archivo de datos activo se ha definido o dentro de INPUT PROGRAM."
 
-#: src/language/command.c:397
+#: src/language/command.c:400
 #, c-format
 msgid "%s is allowed only after the active dataset has been defined or inside FILE TYPE."
 msgstr "%s sólo se permite después que el archivo de datos activo se ha definido o dentro de FILE TYPE."
 
-#: src/language/command.c:401
+#: src/language/command.c:404
 #, c-format
 msgid "%s is allowed only inside INPUT PROGRAM or inside FILE TYPE."
 msgstr "%s sólo se permite dentro de INPUT PROGRAM o FILE TYPE."
 
-#: src/language/command.c:407
+#: src/language/command.c:410
 #, c-format
 msgid "%s is allowed only after the active dataset has been defined, inside INPUT PROGRAM, or inside FILE TYPE."
 msgstr "%s sólo se permite después que el archivo de datos activo se ha definido, dentro de INPUT PROGRAM, o de FILE TYPE."
 
-#: src/language/command.c:412
+#: src/language/command.c:415
 #, c-format
 msgid "%s is allowed only before the active dataset has been defined, inside INPUT PROGRAM, or inside FILE TYPE."
 msgstr "%s sólo se permite antes que el archivo de datos activo se haya definido, dentro de INPUT PROGRAM, o de FILE TYPE."
 
-#: src/language/command.c:430 src/language/command.c:433
+#: src/language/command.c:433 src/language/command.c:436
 #, c-format
 msgid "%s is not allowed inside %s."
 msgstr "%s no está permitido dentro de %s."
 
-#: src/language/command.c:515 src/language/utilities/host.c:130
+#: src/language/command.c:518 src/language/utilities/host.c:130
 #: src/language/utilities/permissions.c:104
 msgid "This command not allowed when the SAFER option is set."
 msgstr "Esta orden no está permitida cuando la opción SAFER está activa."
 
-#: src/language/command.c:531
+#: src/language/command.c:534
 #, c-format
 msgid "Error removing `%s': %s."
 msgstr "Error de eliminación de '%s' : %s."
@@ -1199,55 +1200,55 @@ msgstr "Error de sintaxis en `%s'."
 msgid "Syntax error"
 msgstr "Error de sintaxis"
 
-#: src/language/lexer/lexer.c:1358
+#: src/language/lexer/lexer.c:1363
 #, c-format
 msgid "String of hex digits has %d characters, which is not a multiple of 2"
 msgstr "La cadena hexadecimal tiene %d caracteres, que no es un múltiplo de 2."
 
-#: src/language/lexer/lexer.c:1365
+#: src/language/lexer/lexer.c:1370
 #, c-format
 msgid "`%c' is not a valid hex digit"
 msgstr "`%c' no es un dígito hexadecimal válido."
 
-#: src/language/lexer/lexer.c:1370
+#: src/language/lexer/lexer.c:1375
 #, c-format
 msgid "Unicode string contains %d bytes, which is not in the valid range of 1 to 8 bytes"
 msgstr "Cadena Unicode contiene %d bytes, lo que está fuera del rango válido entre 1 y 8 bytes"
 
-#: src/language/lexer/lexer.c:1376
+#: src/language/lexer/lexer.c:1381
 #, c-format
 msgid "U+%04X is not a valid Unicode code point"
 msgstr "U+%04X no es un punto de código Unicode válido"
 
-#: src/language/lexer/lexer.c:1381
+#: src/language/lexer/lexer.c:1386
 msgid "Unterminated string constant"
 msgstr "Constante de cadena inacabada"
 
-#: src/language/lexer/lexer.c:1385
+#: src/language/lexer/lexer.c:1390
 #, c-format
 msgid "Missing exponent following `%s'"
 msgstr "Falta el exponente a continuación de `%s'"
 
-#: src/language/lexer/lexer.c:1390
+#: src/language/lexer/lexer.c:1395
 msgid "Unexpected `.' in middle of command"
 msgstr "`.' inesperado en mitad de un comando"
 
-#: src/language/lexer/lexer.c:1396
+#: src/language/lexer/lexer.c:1401
 #, c-format
 msgid "Bad character %s in input"
 msgstr "Caracter erróneo `%s' en la entrada"
 
-#: src/language/lexer/lexer.c:1490
+#: src/language/lexer/lexer.c:1495
 #, c-format
 msgid "Opening `%s': %s."
 msgstr "Abriendo `%s': %s."
 
-#: src/language/lexer/lexer.c:1520
+#: src/language/lexer/lexer.c:1525
 #, c-format
 msgid "Error reading `%s': %s."
 msgstr "Error leyendo `%s': %s."
 
-#: src/language/lexer/lexer.c:1534
+#: src/language/lexer/lexer.c:1539
 #, c-format
 msgid "Error closing `%s': %s."
 msgstr "Error cerrando '%s' : %s."
@@ -1472,8 +1473,8 @@ msgstr "El nombre de la variable ficticia `%s' se da dos veces."
 
 #: src/language/control/repeat.c:162
 #, c-format
-msgid "Dummy variable `%s' had %d substitutions, so `%s' must also, but %d were specified."
-msgstr "La variable ficticia `%s' tiene %d substituciones, así que `%s' también tendría que tenerlas, pero se especificaron %d."
+msgid "Dummy variable `%s' had %zu substitutions, so `%s' must also, but %zu were specified."
+msgstr "La variable ficticia `%s' tiene %zu substituciones, así que `%s' también tendría que tenerlas, pero se especificaron %zu."
 
 #: src/language/control/repeat.c:366
 msgid "Ranges may only have integer bounds."
@@ -1518,7 +1519,7 @@ msgstr "esperando %s o %s"
 msgid "Variable %s is %s in target file, but %s in source file."
 msgstr "La variable %s es %s en el archivo de destino, pero %s en el archivo de origen."
 
-#: src/language/dictionary/apply-dictionary.c:111
+#: src/language/dictionary/apply-dictionary.c:110
 msgid "No matching variables found between the source and target files."
 msgstr "No se han encontrado coincidencias de variables entre los archivos de origen y de destino."
 
@@ -1530,11 +1531,11 @@ msgstr "DELETE VARIABLES no puede ser utilizado después de TEMPORARY. Las trans
 msgid "DELETE VARIABLES may not be used to delete all variables from the active dataset dictionary.  Use NEW FILE instead."
 msgstr "DELETE VARIABLES no puede ser utilizado para borrar todas las variables del archivo de datos de diccionario activo. Utilizar NEW FILE en su lugar."
 
-#: src/language/dictionary/formats.c:90
+#: src/language/dictionary/formats.c:87
 msgid "`(' expected after variable list."
 msgstr "`(' esperado después de la lista de variables."
 
-#: src/language/dictionary/formats.c:100 src/language/dictionary/numeric.c:75
+#: src/language/dictionary/formats.c:97 src/language/dictionary/numeric.c:75
 msgid "`)' expected after output format."
 msgstr "`)' esperado después del formato de resultados."
 
@@ -1704,8 +1705,8 @@ msgstr "Conjunto de Categorias Múltiples"
 
 #: src/language/dictionary/mrsets.c:570
 #: src/language/dictionary/split-file.c:84
-#: src/language/dictionary/sys-file-info.c:338
-#: src/language/dictionary/sys-file-info.c:577
+#: src/language/dictionary/sys-file-info.c:336
+#: src/language/dictionary/sys-file-info.c:575
 #: src/ui/gui/psppire-var-sheet.c:538 src/ui/gui/psppire-var-store.c:837
 #: src/ui/gui/compute.ui:467 src/ui/gui/crosstabs.ui:292
 msgid "Label"
@@ -1727,15 +1728,15 @@ msgstr "Proporcionado por el usuario"
 msgid "Counted value"
 msgstr "Valor de recuento"
 
-#: src/language/dictionary/mrsets.c:584
+#: src/language/dictionary/mrsets.c:590
 msgid "Category label source"
 msgstr "Fuente de etiquetas de categoria"
 
-#: src/language/dictionary/mrsets.c:586
+#: src/language/dictionary/mrsets.c:592
 msgid "Variable labels"
 msgstr "Etiquetas de variable"
 
-#: src/language/dictionary/mrsets.c:587
+#: src/language/dictionary/mrsets.c:593
 msgid "Value labels of counted value"
 msgstr "Etiquetas de valor del valor de recuento"
 
@@ -1776,13 +1777,13 @@ msgid "Renaming would duplicate variable name %s."
 msgstr "Cambiar el nombre duplicaría el nombre de la variable %s."
 
 #: src/language/dictionary/split-file.c:83
-#: src/language/dictionary/sys-file-info.c:423
-#: src/language/dictionary/sys-file-info.c:576
+#: src/language/dictionary/sys-file-info.c:421
+#: src/language/dictionary/sys-file-info.c:574
 #: src/language/stats/cochran.c:170 src/language/stats/reliability.c:753
 #: src/language/stats/reliability.c:764 src/language/stats/crosstabs.q:1234
 #: src/language/stats/crosstabs.q:1261 src/language/stats/crosstabs.q:1284
 #: src/language/stats/crosstabs.q:1309 src/language/stats/examine.q:1840
-#: src/language/stats/frequencies.q:823
+#: src/language/stats/frequencies.q:821
 msgid "Value"
 msgstr "Valor"
 
@@ -1860,7 +1861,7 @@ msgid "Type:"
 msgstr "Tipo:"
 
 #: src/language/dictionary/sys-file-info.c:127
-#: src/ui/gui/psppire-data-window.c:621
+#: src/ui/gui/psppire-data-window.c:509
 msgid "System File"
 msgstr "Archivo de Sistema"
 
@@ -1894,13 +1895,13 @@ msgid "Charset:"
 msgstr "Conjunto de carácteres:"
 
 #: src/language/dictionary/sys-file-info.c:150
-#: src/language/dictionary/sys-file-info.c:338
+#: src/language/dictionary/sys-file-info.c:336
 msgid "Description"
 msgstr "Descripción"
 
 #: src/language/dictionary/sys-file-info.c:151
-#: src/language/dictionary/sys-file-info.c:340
-#: src/language/dictionary/sys-file-info.c:657
+#: src/language/dictionary/sys-file-info.c:338
+#: src/language/dictionary/sys-file-info.c:645
 msgid "Position"
 msgstr "Posición"
 
@@ -1908,103 +1909,104 @@ msgstr "Posición"
 msgid "The active dataset does not have a file label."
 msgstr "El archivo de datos activo no tiene etiqueta de archivo."
 
-#: src/language/dictionary/sys-file-info.c:201
-msgid "File label:"
-msgstr "Etiqueta de archivo:"
+#: src/language/dictionary/sys-file-info.c:200
+#, c-format
+msgid "File label: %s"
+msgstr "Etiqueta de archivo: %s"
 
-#: src/language/dictionary/sys-file-info.c:276
+#: src/language/dictionary/sys-file-info.c:274
 msgid "No variables to display."
 msgstr "Ninguna variable para mostrar."
 
-#: src/language/dictionary/sys-file-info.c:290
+#: src/language/dictionary/sys-file-info.c:288
 msgid "Macros not supported."
 msgstr "Macros no disponibles."
 
-#: src/language/dictionary/sys-file-info.c:299
+#: src/language/dictionary/sys-file-info.c:297
 msgid "The active dataset dictionary does not contain any documents."
 msgstr "El diccionario del archivo de datos activo no contiene ningún documento."
 
-#: src/language/dictionary/sys-file-info.c:306
+#: src/language/dictionary/sys-file-info.c:304
 msgid "Documents in the active dataset:"
 msgstr "Documentos en el archivo de datos activo:"
 
-#: src/language/dictionary/sys-file-info.c:422
+#: src/language/dictionary/sys-file-info.c:420
 msgid "Attribute"
 msgstr "Atributo"
 
-#: src/language/dictionary/sys-file-info.c:478
+#: src/language/dictionary/sys-file-info.c:476
 #, c-format
 msgid "Format: %s"
 msgstr "Formato: %s"
 
-#: src/language/dictionary/sys-file-info.c:485
+#: src/language/dictionary/sys-file-info.c:483
 #, c-format
 msgid "Print Format: %s"
 msgstr "Formato de Impresión: %s"
 
-#: src/language/dictionary/sys-file-info.c:489
+#: src/language/dictionary/sys-file-info.c:487
 #, c-format
 msgid "Write Format: %s"
 msgstr "Formato de Escritura: %s"
 
-#: src/language/dictionary/sys-file-info.c:502
+#: src/language/dictionary/sys-file-info.c:500
 #, c-format
 msgid "Measure: %s"
 msgstr "Medida: %s"
 
-#: src/language/dictionary/sys-file-info.c:503
+#: src/language/dictionary/sys-file-info.c:501
 #: src/ui/gui/psppire-var-sheet.c:111
 msgid "Nominal"
 msgstr "Nominal"
 
-#: src/language/dictionary/sys-file-info.c:504
+#: src/language/dictionary/sys-file-info.c:502
 #: src/ui/gui/psppire-var-sheet.c:112
 msgid "Ordinal"
 msgstr "Ordinal"
 
-#: src/language/dictionary/sys-file-info.c:505
+#: src/language/dictionary/sys-file-info.c:503
 #: src/ui/gui/psppire-var-sheet.c:113
 msgid "Scale"
 msgstr "Escala"
 
-#: src/language/dictionary/sys-file-info.c:508
+#: src/language/dictionary/sys-file-info.c:506
 #, c-format
 msgid "Display Alignment: %s"
 msgstr "Alineación de la muestra: %s"
 
-#: src/language/dictionary/sys-file-info.c:509
+#: src/language/dictionary/sys-file-info.c:507
 #: src/ui/gui/psppire-var-sheet.c:104
 msgid "Left"
 msgstr "Izquierda"
 
-#: src/language/dictionary/sys-file-info.c:510
+#: src/language/dictionary/sys-file-info.c:508
 #: src/ui/gui/psppire-var-sheet.c:106
 msgid "Center"
 msgstr "Centro"
 
-#: src/language/dictionary/sys-file-info.c:511
+#: src/language/dictionary/sys-file-info.c:509
 #: src/ui/gui/psppire-var-sheet.c:105
 msgid "Right"
 msgstr "Derecha"
 
-#: src/language/dictionary/sys-file-info.c:514
+#: src/language/dictionary/sys-file-info.c:512
 #, c-format
 msgid "Display Width: %d"
 msgstr "Ancho de la muestra: %d"
 
-#: src/language/dictionary/sys-file-info.c:528
+#: src/language/dictionary/sys-file-info.c:526
 msgid "Missing Values: "
 msgstr "Valores perdidos: "
 
-#: src/language/dictionary/sys-file-info.c:637
+#: src/language/dictionary/sys-file-info.c:625
 msgid "No vectors defined."
 msgstr "Vectores no definidos."
 
-#: src/language/dictionary/sys-file-info.c:656
+#: src/language/dictionary/sys-file-info.c:644
 msgid "Vector"
 msgstr "Vector"
 
-#: src/language/dictionary/sys-file-info.c:659
+#: src/language/dictionary/sys-file-info.c:647
 msgid "Print Format"
 msgstr "Formato de Impresión"
 
@@ -2088,21 +2090,21 @@ msgstr "Error de ejecución del comando: %s."
 msgid "   (Entered %s)"
 msgstr "   (Introducido %s)"
 
-#: src/language/utilities/include.c:64
+#: src/language/utilities/include.c:65
 msgid "expecting file name"
 msgstr "esperando nombre de archivo"
 
-#: src/language/utilities/include.c:74
+#: src/language/utilities/include.c:75
 #, c-format
 msgid "Can't find `%s' in include file search path."
 msgstr "No se puede encontrar `%s' en la ruta de búsqueda del archivo de inclusión."
 
-#: src/language/utilities/include.c:107
+#: src/language/utilities/include.c:109
 #, c-format
 msgid "expecting %s, %s, or %s after %s"
 msgstr "esperando %s, %s, o %s tras %s"
 
-#: src/language/utilities/include.c:125 src/language/utilities/include.c:143
+#: src/language/utilities/include.c:127 src/language/utilities/include.c:145
 #, c-format
 msgid "expecting %s or %s after %s"
 msgstr "esperando %s o %s tras %s"
@@ -2281,7 +2283,7 @@ msgstr "Grupo 2"
 #: src/language/stats/sign.c:95 src/language/stats/wilcoxon.c:255
 #: src/ui/gui/crosstabs-dialog.c:59 src/language/stats/crosstabs.q:832
 #: src/language/stats/crosstabs.q:1176 src/language/stats/crosstabs.q:1560
-#: src/language/stats/examine.q:1104 src/language/stats/frequencies.q:881
+#: src/language/stats/examine.q:1104 src/language/stats/frequencies.q:879
 #: src/language/stats/regression.q:293
 msgid "Total"
 msgstr "Total"
@@ -2298,7 +2300,7 @@ msgstr "Categoría"
 #: src/language/stats/oneway.c:686 src/language/stats/reliability.c:536
 #: src/language/stats/sign.c:74 src/language/stats/wilcoxon.c:238
 #: src/language/stats/crosstabs.q:839 src/language/stats/examine.q:1175
-#: src/language/stats/frequencies.q:1043 src/language/stats/t-test.q:509
+#: src/language/stats/frequencies.q:1041 src/language/stats/t-test.q:509
 #: src/language/stats/t-test.q:529 src/language/stats/t-test.q:629
 #: src/language/stats/t-test.q:1105
 msgid "N"
@@ -2526,7 +2528,7 @@ msgstr "Fuente"
 msgid "Target"
 msgstr "Destino"
 
-#: src/language/stats/descriptives.c:683
+#: src/language/stats/descriptives.c:684
 #, c-format
 msgid "Z-score of %s"
 msgstr "puntuación-Z de %s"
@@ -2576,10 +2578,9 @@ msgstr "Componente"
 msgid "Factor"
 msgstr "Factor"
 
-#: src/language/stats/factor.c:1345 src/language/stats/factor.c:1493
-#: src/ui/gui/psppire-data-store.c:755 src/ui/gui/psppire-var-store.c:700
-#: src/ui/gui/psppire-var-store.c:710 src/ui/gui/psppire-var-store.c:720
-#: src/ui/gui/psppire-var-store.c:826
+#: src/language/stats/factor.c:1345 src/ui/gui/psppire-data-store.c:755
+#: src/ui/gui/psppire-var-store.c:699 src/ui/gui/psppire-var-store.c:709
+#: src/ui/gui/psppire-var-store.c:719 src/ui/gui/psppire-var-store.c:826
 #, c-format
 msgid "%d"
 msgstr "%d"
@@ -2609,6 +2610,11 @@ msgstr "% de Varianza"
 msgid "Cumulative %"
 msgstr "% Acumulado"
 
+#: src/language/stats/factor.c:1493
+#, c-format
+msgid "%zu"
+msgstr "%zu"
+
 #: src/language/stats/factor.c:1576
 msgid "Correlation Matrix"
 msgstr "Matriz de Correlación"
@@ -2774,7 +2780,7 @@ msgid "PAIRED was specified but the number of variables preceding WITH (%zu) did
 msgstr "Se ha especificado PAIRED pero el número de variables antes de WITH (%zu) no coincide con el número de variables posterior (%zu)."
 
 #: src/language/stats/npar-summary.c:142 src/language/stats/examine.q:1995
-#: src/language/stats/examine.q:2012 src/language/stats/frequencies.q:1059
+#: src/language/stats/examine.q:2012 src/language/stats/frequencies.q:1057
 #: src/ui/gui/examine.ui:345
 msgid "Percentiles"
 msgstr "Percentiles"
@@ -2902,6 +2908,37 @@ msgstr "Se asume igualdad de varianzas"
 msgid "Does not assume equal"
 msgstr "No se asume igualdad"
 
+#: src/language/stats/quick-cluster.c:369
+msgid "Number of clusters may not be larger than the number of cases."
+msgstr "El número de agrupaciones no puede ser mayor que el número de casos."
+
+#: src/language/stats/quick-cluster.c:411
+msgid "Final Cluster Centers"
+msgstr "Centros de Agrupaciones Finales"
+
+#: src/language/stats/quick-cluster.c:415
+msgid "Initial Cluster Centers"
+msgstr "Centros de Agrupaciones Iniciales"
+
+#: src/language/stats/quick-cluster.c:418
+#: src/language/stats/quick-cluster.c:472
+msgid "Cluster"
+msgstr "Agrupaciones"
+
+#: src/language/stats/quick-cluster.c:470
+msgid "Number of Cases in each Cluster"
+msgstr "Número de casos en cada Agrupación"
+
+#: src/language/stats/quick-cluster.c:484 src/language/stats/reliability.c:527
+#: src/language/stats/crosstabs.q:830 src/language/stats/examine.q:1102
+#: src/language/stats/frequencies.q:1042
+msgid "Valid"
+msgstr "Válido"
+
+#: src/language/stats/quick-cluster.c:515
+msgid "Variables cannot be parsed"
+msgstr "No se pueden generar las variables"
+
 #: src/language/stats/reliability.c:141
 msgid "Reliability on a single variable is not useful."
 msgstr "El análisis factorial para una única variable es inútil."
@@ -2915,11 +2952,6 @@ msgstr "Resumen del proceso de casos"
 msgid "Cases"
 msgstr "Casos"
 
-#: src/language/stats/reliability.c:527 src/language/stats/crosstabs.q:830
-#: src/language/stats/examine.q:1102 src/language/stats/frequencies.q:1044
-msgid "Valid"
-msgstr "Válido"
-
 #: src/language/stats/reliability.c:530
 msgid "Excluded"
 msgstr "Excluido"
@@ -3151,118 +3183,118 @@ msgstr "Rangos Negativos"
 msgid "Positive Ranks"
 msgstr "Rangos Positivos"
 
-#: src/language/data-io/combine-files.c:211
+#: src/language/data-io/combine-files.c:212
 msgid "Cannot specify the active dataset since none has been defined."
 msgstr "No se puede especificar el fichero de datos activo ya que ningún fichero activo ha sido definido."
 
-#: src/language/data-io/combine-files.c:217
+#: src/language/data-io/combine-files.c:218
 msgid "This command may not be used after TEMPORARY when the active dataset is an input source.  Temporary transformations will be made permanent."
 msgstr "Este comando no puede ser utilizado después de TEMPORARY cuando el archivo de datos activo es una fuente de entrada.  Las transformaciones temporales serán permanentes."
 
-#: src/language/data-io/combine-files.c:251
+#: src/language/data-io/combine-files.c:252
 msgid "Multiple IN subcommands for a single FILE or TABLE."
 msgstr "Múltiples subcomandos IN  per a un único FILE o TABLE."
 
-#: src/language/data-io/combine-files.c:303
+#: src/language/data-io/combine-files.c:304
 #, c-format
 msgid "File %s lacks BY variable %s."
 msgstr "El archivo %s no tiene variable BY %s."
 
-#: src/language/data-io/combine-files.c:306
+#: src/language/data-io/combine-files.c:307
 #, c-format
 msgid "Active dataset lacks BY variable %s."
 msgstr "Archivo de datos activo no tiene BY variable %s."
 
-#: src/language/data-io/combine-files.c:378
+#: src/language/data-io/combine-files.c:379
 msgid "The BY subcommand is required."
 msgstr "Se necesita el subcomando BY."
 
-#: src/language/data-io/combine-files.c:383
-#: src/language/data-io/combine-files.c:388
+#: src/language/data-io/combine-files.c:384
+#: src/language/data-io/combine-files.c:389
 #, c-format
 msgid "BY is required when %s is specified."
 msgstr "BY es necesario cuando se especifica %s."
 
-#: src/language/data-io/combine-files.c:521
+#: src/language/data-io/combine-files.c:514
 msgid "Combining files with incompatible encodings. String data may not be represented correctly."
 msgstr "Combinando archivos con codificaciones incompatibles. Los datos de la cadena no podrán estar representados correctamente."
 
-#: src/language/data-io/combine-files.c:563
+#: src/language/data-io/combine-files.c:555
 #, c-format
 msgid "Variable %s in file %s has different type or width from the same variable in earlier file."
 msgstr "La variable %s en el archivo %s es de tipo o tamaño diferente respecto de la misma variable en un archivo anterior."
 
-#: src/language/data-io/combine-files.c:569
+#: src/language/data-io/combine-files.c:561
 #, c-format
 msgid "In file %s, %s is numeric."
 msgstr "En el archivo %s, %s es numérico."
 
-#: src/language/data-io/combine-files.c:572
+#: src/language/data-io/combine-files.c:564
 #, c-format
 msgid "In file %s, %s is a string variable with width %d."
 msgstr "En el archivo %s, %s es una variable de cadena con ancho %d."
 
-#: src/language/data-io/combine-files.c:577
+#: src/language/data-io/combine-files.c:569
 #, c-format
 msgid "In an earlier file, %s was numeric."
 msgstr "En un archivo anterior, %s era numérico."
 
-#: src/language/data-io/combine-files.c:580
+#: src/language/data-io/combine-files.c:572
 #, c-format
 msgid "In an earlier file, %s was a string variable with width %d."
 msgstr "En un archivo anterior, %s era una variable de cadena con un tamaño de %d."
 
-#: src/language/data-io/combine-files.c:620
+#: src/language/data-io/combine-files.c:612
 #, c-format
 msgid "Variable name %s specified on %s subcommand duplicates an existing variable name."
 msgstr "Nombre de la variable %s especificado en el subcomando %s duplica el nombre de la variable existente."
 
-#: src/language/data-io/combine-files.c:782
+#: src/language/data-io/combine-files.c:774
 #, c-format
 msgid "Encountered %zu sets of duplicate cases in the master file."
 msgstr "Encontrados %zu conjuntos de casos duplicados en el archivo principal."
 
-#: src/language/data-io/data-list.c:137
+#: src/language/data-io/data-list.c:140
 msgid "The END subcommand may only be used within INPUT PROGRAM."
 msgstr "El subcomando END sólo puede ser utilizado dentro de INPUT PROGRAM."
 
-#: src/language/data-io/data-list.c:143
+#: src/language/data-io/data-list.c:146
 msgid "The END subcommand may only be specified once."
 msgstr "El subcomando END sólo puede ser especificado una vez."
 
-#: src/language/data-io/data-list.c:181
+#: src/language/data-io/data-list.c:184
 msgid "Only one of FIXED, FREE, or LIST may be specified."
 msgstr "Sólo uno de FIXED, FREE, o LIST puede ser especificado."
 
-#: src/language/data-io/data-list.c:244
+#: src/language/data-io/data-list.c:245
 msgid "Encoding should not be specified for inline data. It will be ignored."
 msgstr "La codificación no debe ser especificada por los datos en línea. Será ignorada."
 
-#: src/language/data-io/data-list.c:255
+#: src/language/data-io/data-list.c:254
 msgid "The END subcommand may be used only with DATA LIST FIXED."
 msgstr "El subcomando END sólo puede ser utilizado con DATA LIST FIXED."
 
-#: src/language/data-io/data-list.c:270
+#: src/language/data-io/data-list.c:269
 msgid "At least one variable must be specified."
 msgstr "Al menos una variable debe ser especificada."
 
-#: src/language/data-io/data-list.c:369 src/language/data-io/data-list.c:458
+#: src/language/data-io/data-list.c:368 src/language/data-io/data-list.c:457
 #: src/language/data-io/get-data.c:540
 #, c-format
 msgid "%s is a duplicate variable name."
 msgstr "%s es un nombre de variable duplicado."
 
-#: src/language/data-io/data-list.c:376
+#: src/language/data-io/data-list.c:375
 #, c-format
 msgid "There is already a variable %s of a different type."
 msgstr "Ya existe una variable %s de diferente tipo."
 
-#: src/language/data-io/data-list.c:383
+#: src/language/data-io/data-list.c:382
 #, c-format
 msgid "There is already a string variable %s of a different width."
 msgstr "Existe ya una variable de cadena %s con ancho diferente."
 
-#: src/language/data-io/data-list.c:391
+#: src/language/data-io/data-list.c:390
 #, c-format
 msgid "Cannot place variable %s on record %d when RECORDS=%d is specified."
 msgstr "No se puede poner la variable %s en el registro %d cuando RECORDS=%d está especificado."
@@ -3396,6 +3428,23 @@ msgstr "Se ha producido un error al abrir `%s' para escribir en él como un arch
 msgid "I/O error occurred writing data file `%s'."
 msgstr "Error de E/S al escribir los datos del fichero `%s'."
 
+#: src/language/data-io/dataset.c:63
+#, c-format
+msgid "There is no dataset named %s."
+msgstr "No hay ningún archivo de datos llamado %s."
+
+#: src/language/data-io/dataset.c:257
+msgid "Dataset"
+msgstr "Archivo de _Datos"
+
+#: src/language/data-io/dataset.c:265
+msgid "unnamed dataset"
+msgstr "archivo de datos sin nombre"
+
+#: src/language/data-io/dataset.c:269
+msgid "(active dataset)"
+msgstr "(archivo de datos activo)"
+
 #: src/language/data-io/get-data.c:64
 #, c-format
 msgid "Unsupported TYPE %s."
@@ -3758,58 +3807,58 @@ msgstr "Empírico"
 msgid "Empirical with averaging"
 msgstr "Empírico promediado"
 
-#: src/output/ascii.c:281
+#: src/output/ascii.c:298
 #, c-format
 msgid "%s: %s must be positive integer or `auto'"
 msgstr "%s: %s debe ser un entero positivo o `auto'"
 
-#: src/output/ascii.c:314
+#: src/output/ascii.c:331
 #, c-format
 msgid "ascii: page excluding margins and headers must be at least %d characters wide by %d lines long, but as configured is only %d characters by %d lines"
 msgstr "ascii: excluyendo los margenes y encabezamientos la página debe tener como mínimo %d caracteres de ancho por %d líneas de largo, pero tal como está configurada, sólo hay %d caracteres y %d líneas"
 
-#: src/output/ascii.c:363
+#: src/output/ascii.c:377
 #, c-format
 msgid "ascii: closing output file `%s'"
 msgstr "ascii: cerrando el archivo de resultados `%s'"
 
-#: src/output/ascii.c:506
+#: src/output/ascii.c:520
 #, c-format
 msgid "See %s for a chart."
 msgstr "Ver %s para gráfico."
 
-#: src/output/ascii.c:833
+#: src/output/ascii.c:1102
 #, c-format
 msgid "ascii: opening output file `%s'"
 msgstr "ascii: abriendo el archivo de resultados `%s'"
 
-#: src/output/ascii.c:940
+#: src/output/ascii.c:1173
 #, c-format
 msgid "%s - Page %d"
 msgstr "%s - Página %d"
 
-#: src/output/csv.c:97 src/output/html.c:106 src/output/journal.c:93
+#: src/output/csv.c:97 src/output/html.c:104 src/output/journal.c:93
 #: src/output/msglog.c:66
 #, c-format
 msgid "error opening output file `%s'"
 msgstr "error abriendo el fichero de resultados `%s'"
 
 #. TRANSLATORS: Don't translate the words `terminal' or `listing'.
-#: src/output/driver.c:283
+#: src/output/driver.c:319
 #, c-format
 msgid "%s is not a valid device type (the choices are `terminal' and `listing')"
 msgstr "%s no es un tipo de dispositivo válido (las opciones son `terminal' y `listing')"
 
-#: src/output/driver.c:296
+#: src/output/driver.c:332
 #, c-format
 msgid "%s: unknown option `%s'"
 msgstr "%s: opción desconocida `%s'"
 
-#: src/output/html.c:114
+#: src/output/html.c:112
 msgid "PSPP Output"
 msgstr "Resultado de PSPP"
 
-#: src/output/html.c:258
+#: src/output/html.c:238
 msgid "No description"
 msgstr "Sin descripción"
 
@@ -3960,7 +4009,7 @@ msgid "HISTOGRAM"
 msgstr "HISTOGRAM"
 
 #: src/output/charts/plot-hist-cairo.c:112
-#: src/language/stats/frequencies.q:824
+#: src/language/stats/frequencies.q:822
 msgid "Frequency"
 msgstr "Frecuencia"
 
@@ -3988,11 +4037,11 @@ msgstr "Algoritmo tiene que ser o `compatible' o `enhaced'."
 msgid "Syntax must be either `compatible' or `enhanced'."
 msgstr "La sintaxis tiene que ser `compatible' o `enhaced'."
 
-#: src/ui/terminal/main.c:145
+#: src/ui/terminal/main.c:148
 msgid "Error encountered while ERROR=STOP is effective."
 msgstr "Error detectado mientras está activo ERROR=STOP."
 
-#: src/ui/terminal/main.c:151
+#: src/ui/terminal/main.c:154
 msgid "Stopping syntax file processing here to avoid a cascade of dependent command failures."
 msgstr "Deteniendo el procesamiento del archivo de sintaxis aquí para evitar una cascada de errores derivados."
 
@@ -4088,16 +4137,15 @@ msgstr "no se puede acceder a la definición para terminal `%s'"
 msgid "Aggregate destination file"
 msgstr "Archivo de destino para agregación"
 
-#: src/ui/gui/aggregate-dialog.c:172 src/ui/gui/psppire-data-window.c:400
-#: src/ui/gui/psppire-data-window.c:601
+#: src/ui/gui/aggregate-dialog.c:172 src/ui/gui/psppire-data-window.c:489
+#: src/ui/gui/psppire-window.c:763
 msgid "System Files (*.sav)"
 msgstr "Archivos de Sistema (*.sav)"
 
-#: src/ui/gui/aggregate-dialog.c:178 src/ui/gui/psppire-data-window.c:406
-#: src/ui/gui/psppire-data-window.c:607
-#, fuzzy
+#: src/ui/gui/aggregate-dialog.c:178 src/ui/gui/psppire-data-window.c:495
+#: src/ui/gui/psppire-window.c:769
 msgid "Portable Files (*.por) "
-msgstr "Archivos Portátiles (*.por)"
+msgstr "Archivos Portátiles (*.por) "
 
 #: src/ui/gui/checkbox-treeview.c:92 src/language/stats/crosstabs.q:1233
 #: src/language/stats/crosstabs.q:1260 src/language/stats/crosstabs.q:1283
@@ -4164,7 +4212,7 @@ msgstr "Corr"
 
 #: src/ui/gui/crosstabs-dialog.c:53 src/ui/gui/crosstabs-dialog.c:64
 #: src/ui/gui/crosstabs-dialog.c:99 src/ui/gui/crosstabs-dialog.c:107
-#: src/ui/gui/psppire-var-store.c:613 src/ui/gui/var-display.c:16
+#: src/ui/gui/psppire-var-store.c:612 src/ui/gui/var-display.c:16
 #: src/ui/gui/variable-info-dialog.c:41
 msgid "None"
 msgstr "Ninguno"
@@ -4319,19 +4367,19 @@ msgstr "Especificación de intervalo incorrecta"
 msgid "Contrast %d of %d"
 msgstr "Contraste %d de %d"
 
-#: src/ui/gui/psppire.c:218
+#: src/ui/gui/psppire.c:191
 msgid "_Reset"
 msgstr "_Reiniciar"
 
-#: src/ui/gui/psppire.c:219
+#: src/ui/gui/psppire.c:192
 msgid "_Select"
 msgstr "_Selecionar"
 
-#: src/ui/gui/psppire-data-editor.c:950
+#: src/ui/gui/psppire-data-editor.c:970
 msgid "Data View"
 msgstr "Vista de Datos"
 
-#: src/ui/gui/psppire-data-editor.c:953
+#: src/ui/gui/psppire-data-editor.c:973
 msgid "Variable View"
 msgstr "Vista de Variables"
 
@@ -4339,71 +4387,73 @@ msgstr "Vista de Variables"
 msgid "var"
 msgstr "var"
 
-#: src/ui/gui/psppire-data-window.c:212
+#: src/ui/gui/psppire-data-window.c:202
 msgid "Transformations Pending"
 msgstr "Transformaciones pendientes"
 
-#: src/ui/gui/psppire-data-window.c:228
+#: src/ui/gui/psppire-data-window.c:218
 msgid "Filter off"
 msgstr "SIN Filtro"
 
-#: src/ui/gui/psppire-data-window.c:242
+#: src/ui/gui/psppire-data-window.c:232
 #, c-format
 msgid "Filter by %s"
 msgstr "Filtrado por %s"
 
-#: src/ui/gui/psppire-data-window.c:263
+#: src/ui/gui/psppire-data-window.c:253
 msgid "No Split"
 msgstr "NO Dividido"
 
-#: src/ui/gui/psppire-data-window.c:272
+#: src/ui/gui/psppire-data-window.c:262
 msgid "Split by "
 msgstr "Dividido por "
 
-#: src/ui/gui/psppire-data-window.c:300
+#: src/ui/gui/psppire-data-window.c:290
 msgid "Weights off"
 msgstr "SIN Ponderar"
 
-#: src/ui/gui/psppire-data-window.c:314
+#: src/ui/gui/psppire-data-window.c:304
 #, c-format
 msgid "Weight by %s"
 msgstr "Ponderado por %s"
 
-#: src/ui/gui/psppire-data-window.c:380
-msgid "Open"
-msgstr "Abrir"
-
-#: src/ui/gui/psppire-data-window.c:390
-msgid "Data and Syntax Files"
-msgstr "Ficheros de Datos y Sintaxsi"
-
-#: src/ui/gui/psppire-data-window.c:412 src/ui/gui/psppire-syntax-window.c:505
-msgid "Syntax Files (*.sps) "
-msgstr "Archivos de Sintàxis (*.sps) "
+#: src/ui/gui/psppire-data-window.c:481 src/ui/gui/aggregate.ui:448
+msgid "Save"
+msgstr "Guardar"
 
-#: src/ui/gui/psppire-data-window.c:418 src/ui/gui/psppire-data-window.c:613
-#: src/ui/gui/psppire-syntax-window.c:511
+#: src/ui/gui/psppire-data-window.c:501 src/ui/gui/psppire-syntax-window.c:508
+#: src/ui/gui/psppire-window.c:781
 msgid "All Files"
 msgstr "Todos los archivos"
 
-#: src/ui/gui/psppire-data-window.c:593 src/ui/gui/aggregate.ui:448
-msgid "Save"
-msgstr "Guardar"
-
-#: src/ui/gui/psppire-data-window.c:626
+#: src/ui/gui/psppire-data-window.c:514
 msgid "Portable File"
 msgstr "Archivo Portátil"
 
-#: src/ui/gui/psppire-data-window.c:759
+#: src/ui/gui/psppire-data-window.c:571
+msgid "Delete Existing Dataset?"
+msgstr "Eliminar el archivo de datos existente?"
+
+#: src/ui/gui/psppire-data-window.c:575
+#, c-format
+msgid "Renaming \"%s\" to \"%s\" will delete destroy the existing dataset named \"%s\".  Are you sure that you want to do this?"
+msgstr "Renombrar \"%s\" como \"%s\" eliminará el archivo existente llamado \"%s\".  Está seguro de querer hacer eso?"
+
+#: src/ui/gui/psppire-data-window.c:603
+#, c-format
+msgid "Please enter a new name for dataset \"%s\":"
+msgstr "Por favor, introduzca un nombre para el arxhivo de datos \"%s\":"
+
+#: src/ui/gui/psppire-data-window.c:605
+msgid "Rename Dataset"
+msgstr "Renombra el Archivo de datos"
+
+#: src/ui/gui/psppire-data-window.c:684
 msgid "Font Selection"
 msgstr "Selección de fuente"
 
 #. TRANSLATORS: This will form a filename.  Please avoid whitespace.
-#: src/ui/gui/psppire-data-window.c:1256
-msgid "PSPP-data"
-msgstr "datos-PSPP"
-
-#: src/ui/gui/psppire-data-window.c:1257
+#: src/ui/gui/psppire-data-window.c:1287
 msgid "Data Editor"
 msgstr "Editor de Datos"
 
@@ -4464,25 +4514,25 @@ msgstr "Resultado"
 msgid "Output Viewer"
 msgstr "Visor de resultados"
 
-#: src/ui/gui/psppire-syntax-window.c:478
+#: src/ui/gui/psppire-syntax-window.c:475
 #, c-format
 msgid "Saved file `%s'"
 msgstr "Guardado archivo `%s'"
 
-#: src/ui/gui/psppire-syntax-window.c:497
+#: src/ui/gui/psppire-syntax-window.c:494
 msgid "Save Syntax"
 msgstr "Guardar sintaxis"
 
-#. TRANSLATORS: This will form a filename.  Please avoid whitespace.
-#: src/ui/gui/psppire-syntax-window.c:746
-msgid "Syntax"
-msgstr "Sintaxis"
+#: src/ui/gui/psppire-syntax-window.c:502 src/ui/gui/psppire-window.c:775
+msgid "Syntax Files (*.sps) "
+msgstr "Archivos de Sintàxis (*.sps) "
 
-#: src/ui/gui/psppire-syntax-window.c:747
+#. TRANSLATORS: This will form a filename.  Please avoid whitespace.
+#: src/ui/gui/psppire-syntax-window.c:733
 msgid "Syntax Editor"
 msgstr "Editor de sintaxis"
 
-#: src/ui/gui/psppire-syntax-window.c:761
+#: src/ui/gui/psppire-syntax-window.c:747
 #, c-format
 msgid "Cannot load syntax file `%s'"
 msgstr "No se puede abrir el archivo de sintaxis `%s'"
@@ -4507,7 +4557,7 @@ msgstr "Valores"
 
 #: src/ui/gui/psppire-var-sheet.c:540 src/ui/gui/psppire-var-store.c:839
 #: src/language/stats/crosstabs.q:831 src/language/stats/examine.q:1103
-#: src/language/stats/frequencies.q:874 src/language/stats/frequencies.q:1045
+#: src/language/stats/frequencies.q:872 src/language/stats/frequencies.q:1043
 msgid "Missing"
 msgstr "Perdidos"
 
@@ -4519,59 +4569,57 @@ msgstr "Alineación"
 msgid "Measure"
 msgstr "Medida"
 
-#: src/ui/gui/psppire-var-store.c:623 src/ui/gui/var-sheet-dialogs.ui:43
+#: src/ui/gui/psppire-var-store.c:622 src/ui/gui/var-sheet-dialogs.ui:43
 msgid "Comma"
 msgstr "Coma"
 
-#: src/ui/gui/psppire-var-store.c:624 src/ui/gui/var-sheet-dialogs.ui:59
+#: src/ui/gui/psppire-var-store.c:623 src/ui/gui/var-sheet-dialogs.ui:59
 msgid "Dot"
 msgstr "Punto"
 
-#: src/ui/gui/psppire-var-store.c:625
+#: src/ui/gui/psppire-var-store.c:624
 msgid "Scientific"
 msgstr "Científico"
 
-#: src/ui/gui/psppire-var-store.c:626 src/ui/gui/var-sheet-dialogs.ui:91
+#: src/ui/gui/psppire-var-store.c:625 src/ui/gui/var-sheet-dialogs.ui:91
 msgid "Date"
 msgstr "Fecha"
 
-#: src/ui/gui/psppire-var-store.c:627 src/ui/gui/var-sheet-dialogs.ui:107
+#: src/ui/gui/psppire-var-store.c:626 src/ui/gui/var-sheet-dialogs.ui:107
 msgid "Dollar"
 msgstr "Dolar"
 
-#: src/ui/gui/psppire-var-store.c:628
+#: src/ui/gui/psppire-var-store.c:627
 msgid "Custom"
 msgstr "De usuario"
 
-#: src/ui/gui/psppire-var-store.c:756
+#: src/ui/gui/psppire-var-store.c:755
 #, c-format
 msgid "{%s,`%s'}_"
 msgstr "{%s,`%s'}_"
 
-#: src/ui/gui/psppire-window.c:97
-#, c-format
-msgid "%s %s PSPPIRE %s"
-msgstr "%s %s PSPPIRE %s"
-
-#. TRANSLATORS: This will form a filename.  Please avoid whitespace.
-#: src/ui/gui/psppire-window.c:247
-msgid "Untitled"
-msgstr "Sin título"
-
-#: src/ui/gui/psppire-window.c:469
+#: src/ui/gui/psppire-window.c:549
 #, c-format
 msgid "Save the changes to `%s' before closing?"
 msgstr "¿Guardar los cambios en `%s' antes de salir?"
 
-#: src/ui/gui/psppire-window.c:476
+#: src/ui/gui/psppire-window.c:556
 #, c-format
 msgid "If you don't save, changes from the last %ld seconds will be permanently lost."
 msgstr "Si no se guarda ahora, los cambios de los últims %ld segundos se perderan permanentemente."
 
-#: src/ui/gui/psppire-window.c:480
+#: src/ui/gui/psppire-window.c:560
 msgid "Close _without saving"
 msgstr "Cerrar sin guardar"
 
+#: src/ui/gui/psppire-window.c:743
+msgid "Open"
+msgstr "Abrir"
+
+#: src/ui/gui/psppire-window.c:753
+msgid "Data and Syntax Files"
+msgstr "Ficheros de Datos y Sintaxsi"
+
 #: src/ui/gui/recode-dialog.c:886
 msgid "Recode into Different Variables"
 msgstr "Recodificar en variables Diferentes"
@@ -4627,45 +4675,45 @@ msgstr "Exactamente %3d casos de los primeros %3d casos."
 msgid "%d thru %d"
 msgstr "%d hasta %d"
 
-#: src/ui/gui/text-data-import-dialog.c:452
+#: src/ui/gui/text-data-import-dialog.c:453
 #, c-format
 msgid "Could not open `%s': %s"
 msgstr "No se puede abrir `%s': %s"
 
-#: src/ui/gui/text-data-import-dialog.c:468
+#: src/ui/gui/text-data-import-dialog.c:469
 #, c-format
 msgid "Error reading `%s': %s"
 msgstr "Error leyendo `%s': %s"
 
-#: src/ui/gui/text-data-import-dialog.c:471
+#: src/ui/gui/text-data-import-dialog.c:472
 #, c-format
 msgid "Failed to read `%s', because it contains a line over %d bytes long and therefore appears not to be a text file."
 msgstr "Error leyendo `%s', porque contiene una linea más allá de %d bytes y por tanto parece que no es un archivo de texto."
 
-#: src/ui/gui/text-data-import-dialog.c:485
+#: src/ui/gui/text-data-import-dialog.c:486
 #, c-format
 msgid "`%s' is empty."
 msgstr "`%s' esta vacío."
 
-#: src/ui/gui/text-data-import-dialog.c:530
+#: src/ui/gui/text-data-import-dialog.c:531
 msgid "Import Delimited Text Data"
 msgstr "Importar datos de texto delimitado"
 
-#: src/ui/gui/text-data-import-dialog.c:581
+#: src/ui/gui/text-data-import-dialog.c:582
 msgid "Importing Delimited Text Data"
 msgstr "Importando datos de texto delimitado"
 
-#: src/ui/gui/text-data-import-dialog.c:730
+#: src/ui/gui/text-data-import-dialog.c:731
 #, c-format
 msgid "Only the first %4d cases"
 msgstr "Sólo los primeros %4d casos"
 
-#: src/ui/gui/text-data-import-dialog.c:740
+#: src/ui/gui/text-data-import-dialog.c:741
 #, c-format
 msgid "Only the first %3d %% of file (approximately)"
 msgstr "Sólo los primeros %3d %% del archivo (aproximadamente)"
 
-#: src/ui/gui/text-data-import-dialog.c:765
+#: src/ui/gui/text-data-import-dialog.c:766
 msgid ""
 "This assistant will guide you through the process of importing data into PSPP from a text file with one line per case,  in which fields are separated by tabs, commas, or other delimiters.\n"
 "\n"
@@ -4673,46 +4721,46 @@ msgstr ""
 "Este asistente te quiará a lo largo del proceso de importar datos en PSPP desde un archivo de texto con una línea por caso,  en el que los campos estan separados por tabuladores, comas, u otros delimitadores.\n"
 "\n"
 
-#: src/ui/gui/text-data-import-dialog.c:771
+#: src/ui/gui/text-data-import-dialog.c:772
 #, c-format
 msgid "The selected file contains %zu line of text.  "
 msgid_plural "The selected file contains %zu lines of text.  "
 msgstr[0] "L'arxiu seleccionat conté %zu linies de text.  "
 msgstr[1] "El archivo seleccionado contiene %zu línias de texto.  "
 
-#: src/ui/gui/text-data-import-dialog.c:779
+#: src/ui/gui/text-data-import-dialog.c:780
 #, c-format
 msgid "The selected file contains approximately %lu line of text.  "
 msgid_plural "The selected file contains approximately %lu lines of text.  "
 msgstr[0] "El archivo seleccionado contiene aproximadamente %lu línea de texto.  "
 msgstr[1] "El archivo seleccionado contiene aproximadamente %lu líneas de texto.  "
 
-#: src/ui/gui/text-data-import-dialog.c:785
+#: src/ui/gui/text-data-import-dialog.c:786
 #, c-format
 msgid "Only the first %zu line of the file will be shown for preview purposes in the following screens.  "
 msgid_plural "Only the first %zu lines of the file will be shown for preview purposes in the following screens.  "
 msgstr[0] "Únicamente la primera %zu líneas del archivo se previsualizaran en las siguientes pantallas.  "
 msgstr[1] "Únicamente las primeras %zu líneas del archivo se previsualizaran en las siguientes pantallas.  "
 
-#: src/ui/gui/text-data-import-dialog.c:792
+#: src/ui/gui/text-data-import-dialog.c:793
 msgid "You may choose below how much of the file should actually be imported."
 msgstr "Puedes escoger a continuación que parte del archivo va a ser importado."
 
-#: src/ui/gui/text-data-import-dialog.c:875
+#: src/ui/gui/text-data-import-dialog.c:876
 msgid "Text"
 msgstr "Texto"
 
-#: src/ui/gui/text-data-import-dialog.c:1539
-#: src/ui/gui/text-data-import-dialog.c:1785
+#: src/ui/gui/text-data-import-dialog.c:1540
+#: src/ui/gui/text-data-import-dialog.c:1786
 msgid "This input line has too few separators to fill in this field."
 msgstr "Esta línea de entrada no tiene suficientes separadores para llenar el campo."
 
-#: src/ui/gui/text-data-import-dialog.c:1776
+#: src/ui/gui/text-data-import-dialog.c:1777
 #, c-format
 msgid "Cannot parse field content `%.*s' as format %s: %s"
 msgstr "No se puede analizar el contenido de campo `%.*s' como formato %s: %s"
 
-#: src/ui/gui/text-data-import-dialog.c:1929
+#: src/ui/gui/text-data-import-dialog.c:1930
 msgid "Line"
 msgstr "Línea"
 
@@ -4721,7 +4769,7 @@ msgstr "Línea"
 msgid "Confidence Interval: %2d %%"
 msgstr "Intervalo de Confianza: %2d %%"
 
-#: src/ui/gui/val-labs-dialog.c:515
+#: src/ui/gui/val-labs-dialog.c:519
 #, c-format
 msgid "%s = `%s'"
 msgstr "%s = `%s'"
@@ -4741,16 +4789,16 @@ msgstr "Tipo: %s\n"
 msgid "Missing Values: %s\n"
 msgstr "Valores perdidos: %s\n"
 
-#: src/ui/gui/variable-info-dialog.c:93
+#: src/ui/gui/variable-info-dialog.c:92
 #, c-format
 msgid "Measurement Level: %s\n"
 msgstr "Nivel de Medida: %s\n"
 
-#: src/ui/gui/variable-info-dialog.c:106
+#: src/ui/gui/variable-info-dialog.c:105
 msgid "Value Labels:\n"
 msgstr "Etiquetas de valor:\n"
 
-#: src/ui/gui/variable-info-dialog.c:116
+#: src/ui/gui/variable-info-dialog.c:115
 #, c-format
 msgid "%s %s\n"
 msgstr "%s %s\n"
@@ -4935,7 +4983,7 @@ msgid "Summary."
 msgstr "Resumen."
 
 #: src/language/stats/crosstabs.q:840 src/language/stats/examine.q:1178
-#: src/language/stats/frequencies.q:825
+#: src/language/stats/frequencies.q:823
 msgid "Percent"
 msgstr "Porcentaje"
 
@@ -5188,113 +5236,113 @@ msgstr "Bisagras de Tukey"
 msgid "%g"
 msgstr "%g"
 
-#: src/language/stats/frequencies.q:382
+#: src/language/stats/frequencies.q:381
 msgid "Bar charts are not implemented."
 msgstr "El gráfico de barras no está implementado."
 
-#: src/language/stats/frequencies.q:399
+#: src/language/stats/frequencies.q:398
 #, c-format
 msgid "MAX for histogram must be greater than or equal to MIN, but MIN was specified as %.15g and MAX as %.15g.  MIN and MAX will be ignored."
 msgstr "Para el histograma, MAX debe ser mayor o igual a MIN, pero MIN se ha especificado como %15g y MAX como %15g.  MIN y MAX serán ignorados."
 
-#: src/language/stats/frequencies.q:420
+#: src/language/stats/frequencies.q:419
 #, c-format
 msgid "MAX for pie chart must be greater than or equal to MIN, but MIN was specified as %.15g and MAX as %.15g.  MIN and MAX will be ignored."
 msgstr "Para el gráfico de sectores, MAX debe ser mayor o igual a MIN, pero MIN se ha especificado como %15g y MAX como %15g.  MIN y MAX serán ignorados."
 
-#: src/language/stats/frequencies.q:704
+#: src/language/stats/frequencies.q:702
 msgid "`)' expected after GROUPED interval list."
 msgstr "`)' esperada después de la lista de variables GRUPED."
 
-#: src/language/stats/frequencies.q:724
+#: src/language/stats/frequencies.q:722
 #, c-format
 msgid "Variables %s specified multiple times on GROUPED subcommand."
 msgstr "La variable %s se ha especificado más de una vez en el subcomando GROUPED."
 
-#: src/language/stats/frequencies.q:734
+#: src/language/stats/frequencies.q:732
 #, c-format
 msgid "Variables %s specified on GROUPED but not on VARIABLES."
 msgstr "Variables %s especificadas en GROUPED pero no en VARIABLES."
 
-#: src/language/stats/frequencies.q:822
+#: src/language/stats/frequencies.q:820
 msgid "Value Label"
 msgstr "Etiqueta de Valor"
 
-#: src/language/stats/frequencies.q:826
+#: src/language/stats/frequencies.q:824
 msgid "Valid Percent"
 msgstr "Porcentaje Válido"
 
-#: src/language/stats/frequencies.q:827
+#: src/language/stats/frequencies.q:825
 msgid "Cum Percent"
 msgstr "Porcentaje Acumulado"
 
-#: src/language/stats/frequencies.q:1017
+#: src/language/stats/frequencies.q:1015
 #, c-format
 msgid "No valid data for variable %s; statistics not displayed."
 msgstr "No hay datos válidos para la variable %s; no se muestran estadísticas."
 
-#: src/language/stats/frequencies.q:1063
+#: src/language/stats/frequencies.q:1061
 msgid "50 (Median)"
 msgstr "50 (Mediana)"
 
-#: src/language/stats/frequencies.q:1218
+#: src/language/stats/frequencies.q:1217
 #, c-format
 msgid "Omitting pie chart for %s, which has only %d unique values."
 msgstr "Se omite el gráfico de sectores para %s, que sólo tiene %d valores únicos."
 
-#: src/language/stats/frequencies.q:1221
+#: src/language/stats/frequencies.q:1220
 #, c-format
 msgid "Omitting pie chart for %s, which has over 50 unique values."
 msgstr "Se omite el gráfico de sectores para %s, que tiene más de 50 valores únicos."
 
-#: src/language/stats/rank.q:220
+#: src/language/stats/rank.q:219
 #, c-format
 msgid "%s of %s by %s"
 msgstr "%s de %s para %s"
 
-#: src/language/stats/rank.q:225
+#: src/language/stats/rank.q:224
 #, c-format
 msgid "%s of %s"
 msgstr "%s de %s"
 
-#: src/language/stats/rank.q:600
+#: src/language/stats/rank.q:599
 msgid "Cannot create new rank variable.  All candidates in use."
 msgstr "No se puede crear la nueva variable de rangos.  Todos los candidatos están en uso."
 
-#: src/language/stats/rank.q:696
+#: src/language/stats/rank.q:694
 msgid "Variables Created By RANK"
 msgstr "Variables creadas para RANK"
 
-#: src/language/stats/rank.q:720
+#: src/language/stats/rank.q:718
 #, c-format
 msgid "%s into %s(%s of %s using %s BY %s)"
 msgstr "%s en %s(%s de %s utilizando %s BY %s)"
 
-#: src/language/stats/rank.q:730
+#: src/language/stats/rank.q:728
 #, c-format
 msgid "%s into %s(%s of %s BY %s)"
 msgstr "%s en %s(%s de %s BY %s)"
 
-#: src/language/stats/rank.q:743
+#: src/language/stats/rank.q:741
 #, c-format
 msgid "%s into %s(%s of %s using %s)"
 msgstr "%s en %s(%s de %s utilizando %s)"
 
-#: src/language/stats/rank.q:752
+#: src/language/stats/rank.q:750
 #, c-format
 msgid "%s into %s(%s of %s)"
 msgstr "%s en %s(%s de %s)"
 
-#: src/language/stats/rank.q:764
+#: src/language/stats/rank.q:762
 msgid "FRACTION has been specified, but NORMAL and PROPORTION rank functions have not been requested.  The FRACTION subcommand will be ignored."
 msgstr "Se ha especificado FRACTION, pero no se han pedido funciones de rango NORMAL o PROPORTION.  La suborden FRACTION será ignorada."
 
-#: src/language/stats/rank.q:855
+#: src/language/stats/rank.q:853
 #, c-format
 msgid "Variable %s already exists."
 msgstr "La variable %s ya existe."
 
-#: src/language/stats/rank.q:860
+#: src/language/stats/rank.q:858
 msgid "Too many variables in INTO clause."
 msgstr "Demasiadas variables a la cláusula INTO."
 
@@ -5468,38 +5516,38 @@ msgstr "Correlación"
 msgid "%s & %s"
 msgstr "%s & %s"
 
-#: src/language/data-io/file-handle.q:68
+#: src/language/data-io/file-handle.q:70
 #, c-format
 msgid "File handle %s is already defined.  Use CLOSE FILE HANDLE before redefining a file handle."
 msgstr "El manipulador de archivo %s ya está definido.  Usar CLOSE FILE HANDLE antes de redefinir un manipulador de archivos."
 
-#: src/language/data-io/file-handle.q:123
+#: src/language/data-io/file-handle.q:122
 msgid "RECFORM must be specified with MODE=360."
 msgstr "RECFORM debe ser especificado con MODE=360."
 
-#: src/language/data-io/file-handle.q:134
+#: src/language/data-io/file-handle.q:133
 #, c-format
 msgid "The specified file mode requires LRECL.  Assuming %zu-character records."
 msgstr "El modo de fichero especificado requiere LRECL. Se asumen registros de %zu caracteres."
 
-#: src/language/data-io/file-handle.q:138
+#: src/language/data-io/file-handle.q:137
 #, c-format
-msgid "Record length (%ld) must be between 1 and %lu bytes.  Assuming %d-character records."
-msgstr "El tamaño de registro (%ld) debe estar entre  1 y %lu bytes.  Se asume %d-registros de carácter."
+msgid "Record length (%ld) must be between 1 and %lu bytes.  Assuming %zu-character records."
+msgstr "El tamaño de registro (%ld) debe estar entre 1 y %lu bytes.  Se asume %zu-registros de carácter."
 
-#: src/language/data-io/file-handle.q:182
+#: src/language/data-io/file-handle.q:178
 msgid "file"
 msgstr "archivo"
 
-#: src/language/data-io/file-handle.q:184
+#: src/language/data-io/file-handle.q:180
 msgid "inline file"
 msgstr "archivo en línea"
 
-#: src/language/data-io/file-handle.q:210
+#: src/language/data-io/file-handle.q:228
 msgid "expecting a file name or handle name"
 msgstr "esperando un nombre de archivo o un manipulador"
 
-#: src/language/data-io/file-handle.q:231
+#: src/language/data-io/file-handle.q:243
 #, c-format
 msgid "Handle for %s not allowed here."
 msgstr "Aquí no está permitido un manipulador para %s."
@@ -5865,7 +5913,7 @@ msgstr "Factorización de Ejes Principales"
 msgid "Factor Analysis"
 msgstr "Análisis Factorial"
 
-#: src/ui/gui/factor.ui:55
+#: src/ui/gui/factor.ui:55 src/ui/gui/data-editor.ui:343
 msgid "_Descriptives..."
 msgstr "_Descriptivos..."
 
@@ -6127,7 +6175,7 @@ msgstr "_Factor:"
 msgid "Dependent _Variable(s):"
 msgstr "_Variable(s) Dependientes:"
 
-#: src/ui/gui/oneway.ui:184 src/ui/gui/data-editor.ui:332
+#: src/ui/gui/oneway.ui:184
 msgid "_Descriptives"
 msgstr "_Descriptivos"
 
@@ -6819,323 +6867,376 @@ msgid "_File"
 msgstr "_Archivo"
 
 #: src/ui/gui/data-editor.ui:35 src/ui/gui/syntax-editor.ui:22
-#: src/ui/gui/syntax-editor.ui:40
 msgid "_Syntax"
 msgstr "_Sintaxis"
 
-#: src/ui/gui/data-editor.ui:41 src/ui/gui/data-editor.ui:214
-#: src/ui/gui/data-editor.ui:226 src/ui/gui/syntax-editor.ui:28
-#: src/ui/gui/syntax-editor.ui:46
+#: src/ui/gui/data-editor.ui:41 src/ui/gui/data-editor.ui:224
+#: src/ui/gui/data-editor.ui:237 src/ui/gui/syntax-editor.ui:28
 msgid "_Data"
 msgstr "_Datos"
 
-#: src/ui/gui/data-editor.ui:53
-msgid "_Import Delimited Text Data"
-msgstr "_Importar datos de texto delimitados"
+#: src/ui/gui/data-editor.ui:48 src/ui/gui/syntax-editor.ui:35
+msgid "_Open..."
+msgstr "Abrir..."
+
+#: src/ui/gui/data-editor.ui:54
+msgid "_Import Delimited Text Data..."
+msgstr "_Importar Datos de Texto Delimitados..."
+
+#: src/ui/gui/data-editor.ui:61
+msgid "_Rename Dataset..."
+msgstr "_Renombrar Arxhivo de Datos..."
 
-#: src/ui/gui/data-editor.ui:72
+#: src/ui/gui/data-editor.ui:74 src/ui/gui/syntax-editor.ui:48
+msgid "Save _As..."
+msgstr "Guard_ar como..."
+
+#: src/ui/gui/data-editor.ui:80
 msgid "D_isplay Data File Information"
 msgstr "Muestra _información del archivo de datos"
 
-#: src/ui/gui/data-editor.ui:79
+#: src/ui/gui/data-editor.ui:87
 msgid "Working File"
 msgstr "Archivos de trabajo"
 
-#: src/ui/gui/data-editor.ui:85
-msgid "External File"
-msgstr "Archivo externo"
+#: src/ui/gui/data-editor.ui:93
+msgid "External File..."
+msgstr "Archivo externo..."
 
-#: src/ui/gui/data-editor.ui:91
+#: src/ui/gui/data-editor.ui:99
 msgid "Recently Used Da_ta"
 msgstr "Datos utilizados recientemente"
 
-#: src/ui/gui/data-editor.ui:97
+#: src/ui/gui/data-editor.ui:105
 msgid "Recently Used _Files"
 msgstr "Archivos utilizados recientemente"
 
-#: src/ui/gui/data-editor.ui:109 src/ui/gui/output-viewer.ui:28
-#: src/ui/gui/syntax-editor.ui:70
+#: src/ui/gui/data-editor.ui:117 src/ui/gui/output-viewer.ui:29
+#: src/ui/gui/syntax-editor.ui:60
 msgid "_Edit"
 msgstr "_Editar"
 
-#: src/ui/gui/data-editor.ui:115
+#: src/ui/gui/data-editor.ui:123
 msgid "Insert Variable"
 msgstr "Insertar Variable"
 
-#: src/ui/gui/data-editor.ui:116
+#: src/ui/gui/data-editor.ui:124
 msgid "Create a new variable at the current position"
 msgstr "Crear una nueva variable en la posición seleccionada"
 
-#: src/ui/gui/data-editor.ui:123
+#: src/ui/gui/data-editor.ui:131
 msgid "Insert Cases"
 msgstr "Insertar Casos"
 
-#: src/ui/gui/data-editor.ui:124
+#: src/ui/gui/data-editor.ui:132
 msgid "Create a new case at the current position"
 msgstr "Crear un nuevo caso en la posición actual"
 
-#: src/ui/gui/data-editor.ui:130
-msgid "Go To Case"
-msgstr "Ir al Caso"
+#: src/ui/gui/data-editor.ui:138
+msgid "Go To Case..."
+msgstr "Ir al Caso..."
 
-#: src/ui/gui/data-editor.ui:132
+#: src/ui/gui/data-editor.ui:140
 msgid "Jump to a case in the data sheet"
 msgstr "Ir a un caso en la matriz de datos"
 
-#: src/ui/gui/data-editor.ui:158
+#: src/ui/gui/data-editor.ui:166
 msgid "Cl_ear Variables"
 msgstr "_Eliminar Variables"
 
-#: src/ui/gui/data-editor.ui:159
+#: src/ui/gui/data-editor.ui:167
 msgid "Delete the variables at the selected position(s)"
 msgstr "Borra las variables en la posición(es) seleccionada(s)"
 
-#: src/ui/gui/data-editor.ui:167
+#: src/ui/gui/data-editor.ui:175
 msgid "_Clear Cases"
 msgstr "Eliminar _Casos"
 
-#: src/ui/gui/data-editor.ui:168
+#: src/ui/gui/data-editor.ui:176
 msgid "Delete the cases at the selected position(s)"
 msgstr "Borra los casos en la(s) posición(es) seleccionada(s)"
 
-#: src/ui/gui/data-editor.ui:180
+#: src/ui/gui/data-editor.ui:183
+msgid "_Find..."
+msgstr "Buscar..."
+
+#: src/ui/gui/data-editor.ui:189
 msgid "_View"
 msgstr "_Vista"
 
-#: src/ui/gui/data-editor.ui:187
+#: src/ui/gui/data-editor.ui:196
 msgid "_Status Bar"
 msgstr "Barra de E_stado"
 
-#: src/ui/gui/data-editor.ui:200
+#: src/ui/gui/data-editor.ui:203
+msgid "_Font..."
+msgstr "_Fuentes..."
+
+#: src/ui/gui/data-editor.ui:210
 msgid "_Grid Lines"
 msgstr "Línias divisorias"
 
-#: src/ui/gui/data-editor.ui:206
+#: src/ui/gui/data-editor.ui:216
 msgid "Value _Labels"
 msgstr "Etiquetas de Valor"
 
-#: src/ui/gui/data-editor.ui:207
+#: src/ui/gui/data-editor.ui:217
 msgid "Show/hide value labels"
 msgstr "Muestra/Oculta etiquetas de valor"
 
-#: src/ui/gui/data-editor.ui:220 src/ui/gui/data-editor.ui:440
+#: src/ui/gui/data-editor.ui:230
 msgid "_Variables"
 msgstr "_Variables"
 
-#: src/ui/gui/data-editor.ui:231
-msgid "_Sort Cases"
-msgstr "Ordenar Caso_s"
+#: src/ui/gui/data-editor.ui:242
+msgid "_Sort Cases..."
+msgstr "Ordenar Caso_s..."
 
-#: src/ui/gui/data-editor.ui:234
+#: src/ui/gui/data-editor.ui:245
 msgid "Sort cases in the active dataset"
 msgstr "Ordenar casos en el archivo de datos activo"
 
-#: src/ui/gui/data-editor.ui:241
-msgid "_Transpose"
-msgstr "_Trasponer"
+#: src/ui/gui/data-editor.ui:252
+msgid "_Transpose..."
+msgstr "_Trasponer..."
 
-#: src/ui/gui/data-editor.ui:242
+#: src/ui/gui/data-editor.ui:253
 msgid "Transpose the cases with the variables"
 msgstr "Transponer casos y variables"
 
-#: src/ui/gui/data-editor.ui:249
-msgid "_Aggregate"
-msgstr "_Agregar"
+#: src/ui/gui/data-editor.ui:260
+msgid "_Aggregate..."
+msgstr "_Agregar..."
 
-#: src/ui/gui/data-editor.ui:255
-msgid "S_plit File"
-msgstr "Dividir Archivo"
+#: src/ui/gui/data-editor.ui:266
+msgid "S_plit File..."
+msgstr "Dividir Archivo..."
 
-#: src/ui/gui/data-editor.ui:256
+#: src/ui/gui/data-editor.ui:267
 msgid "Split the active dataset"
 msgstr "Dividir el archivo de datos activo"
 
-#: src/ui/gui/data-editor.ui:263
-msgid "Select _Cases"
-msgstr "Seleccionar _Casos"
+#: src/ui/gui/data-editor.ui:274
+msgid "Select _Cases..."
+msgstr "Seleccionar _Casos..."
 
-#: src/ui/gui/data-editor.ui:269
-msgid "_Weight Cases"
-msgstr "Ponderar Casos"
+#: src/ui/gui/data-editor.ui:280
+msgid "_Weight Cases..."
+msgstr "Ponderar Casos..."
 
-#: src/ui/gui/data-editor.ui:270
+#: src/ui/gui/data-editor.ui:281
 msgid "Weight cases by variable"
 msgstr "Pondera casos por la variable"
 
-#: src/ui/gui/data-editor.ui:277
+#: src/ui/gui/data-editor.ui:288
 msgid "_Transform"
 msgstr "_Transformar"
 
-#: src/ui/gui/data-editor.ui:283
-msgid "_Compute"
-msgstr "_Calcular"
+#: src/ui/gui/data-editor.ui:294
+msgid "_Compute..."
+msgstr "_Calcular..."
 
-#: src/ui/gui/data-editor.ui:289
-msgid "Ran_k Cases"
-msgstr "Rango de casos"
+#: src/ui/gui/data-editor.ui:300
+msgid "Ran_k Cases..."
+msgstr "Rango de Casos..."
 
-#: src/ui/gui/data-editor.ui:295
-msgid "Recode into _Same Variables"
-msgstr "Recodificar en las Misma_s Variables"
+#: src/ui/gui/data-editor.ui:306
+msgid "Recode into _Same Variables..."
+msgstr "Recodificar en las Misma_s Variables..."
 
-#: src/ui/gui/data-editor.ui:301
-msgid "Recode into _Different Variables"
-msgstr "Recodificar en variables _Diferentes"
+#: src/ui/gui/data-editor.ui:312
+msgid "Recode into _Different Variables..."
+msgstr "Recodificar en Variables _Diferentes..."
 
-#: src/ui/gui/data-editor.ui:307
+#: src/ui/gui/data-editor.ui:318
 msgid "_Run Pending Transforms"
 msgstr "Ejecuta_r Transformaciones pendientes"
 
-#: src/ui/gui/data-editor.ui:314
+#: src/ui/gui/data-editor.ui:325
 msgid "_Analyze"
 msgstr "_Analizar"
 
-#: src/ui/gui/data-editor.ui:320
+#: src/ui/gui/data-editor.ui:331
 msgid "_Descriptive Statistics"
 msgstr "Estadística _Descriptiva"
 
-#: src/ui/gui/data-editor.ui:326
-msgid "_Frequencies"
-msgstr "_Frecuencias"
+#: src/ui/gui/data-editor.ui:337
+msgid "_Frequencies..."
+msgstr "_Frecuencias..."
 
-#: src/ui/gui/data-editor.ui:338
-msgid "_Explore"
-msgstr "_Explorar"
+#: src/ui/gui/data-editor.ui:349
+msgid "_Explore..."
+msgstr "_Explorar..."
 
-#: src/ui/gui/data-editor.ui:344
-msgid "_Crosstabs"
-msgstr "Tablas _Cruzadas"
+#: src/ui/gui/data-editor.ui:355
+msgid "_Crosstabs..."
+msgstr "Tablas _Cruzadas..."
 
-#: src/ui/gui/data-editor.ui:350
+#: src/ui/gui/data-editor.ui:361
 msgid "Compare _Means"
 msgstr "Comparar _Medias"
 
-#: src/ui/gui/data-editor.ui:356
-msgid "_One Sample T Test"
-msgstr "Prueba T para una muestra"
+#: src/ui/gui/data-editor.ui:367
+msgid "_One Sample T Test..."
+msgstr "Prueba T para Una Muestra..."
 
-#: src/ui/gui/data-editor.ui:362
-msgid "_Independent Samples T Test"
-msgstr "Prueba T para muestras _Independientes"
+#: src/ui/gui/data-editor.ui:373
+msgid "_Independent Samples T Test..."
+msgstr "Prueba T para Muestras _Independientes..."
 
-#: src/ui/gui/data-editor.ui:368
-msgid "_Paired Samples T Test"
-msgstr "Prueba T para muestras Em_parejadas"
+#: src/ui/gui/data-editor.ui:379
+msgid "_Paired Samples T Test..."
+msgstr "Prueba T para Muestras Em_parejadas..."
 
-#: src/ui/gui/data-editor.ui:374
-msgid "One Way _ANOVA"
-msgstr "_ANOVA de un factor"
+#: src/ui/gui/data-editor.ui:385
+msgid "One Way _ANOVA..."
+msgstr "_ANOVA de un factor..."
 
-#: src/ui/gui/data-editor.ui:380
+#: src/ui/gui/data-editor.ui:391
 msgid "Bivariate _Correlation..."
 msgstr "_Correlación Bivariada..."
 
-#: src/ui/gui/data-editor.ui:386
-msgid "Factor _Analysis"
-msgstr "_Análisis Factorial"
+#: src/ui/gui/data-editor.ui:397
+msgid "Factor _Analysis..."
+msgstr "_Análisis Factorial..."
 
-#: src/ui/gui/data-editor.ui:392
-msgid "Re_liability"
-msgstr "Fiabi_lidad"
+#: src/ui/gui/data-editor.ui:403
+msgid "Re_liability..."
+msgstr "Fiabi_lidad..."
 
-#: src/ui/gui/data-editor.ui:398
-msgid "Linear _Regression"
-msgstr "_Regresión Lineal"
+#: src/ui/gui/data-editor.ui:409
+msgid "Linear _Regression..."
+msgstr "_Regresión Lineal..."
 
-#: src/ui/gui/data-editor.ui:404
+#: src/ui/gui/data-editor.ui:415
 msgid "_Non-Parametric Statistics"
 msgstr "Pruebas _No-Paramétricas"
 
-#: src/ui/gui/data-editor.ui:410
-msgid "_Chi-Square"
-msgstr "_Chi-cuadrado"
+#: src/ui/gui/data-editor.ui:421
+msgid "_Chi-Square..."
+msgstr "_Chi-cuadrado..."
 
-#: src/ui/gui/data-editor.ui:416
-msgid "_Binomial"
-msgstr "_Binomial"
+#: src/ui/gui/data-editor.ui:427
+msgid "_Binomial..."
+msgstr "_Binomial..."
 
-#: src/ui/gui/data-editor.ui:422
-msgid "K Related _Samples"
-msgstr "K Muestra_s Relacionadas"
+#: src/ui/gui/data-editor.ui:433
+msgid "K Related _Samples..."
+msgstr "K Muestra_s Emparejadas..."
 
-#: src/ui/gui/data-editor.ui:428
+#: src/ui/gui/data-editor.ui:439
 msgid "ROC Cur_ve..."
 msgstr "Curva ROC"
 
-#: src/ui/gui/data-editor.ui:434
+#: src/ui/gui/data-editor.ui:445
 msgid "_Utilities"
 msgstr "_Utilidades"
 
-#: src/ui/gui/data-editor.ui:441
+#: src/ui/gui/data-editor.ui:451
+msgid "_Variables..."
+msgstr "_Variables..."
+
+#: src/ui/gui/data-editor.ui:452
 msgid "Jump to variable"
 msgstr "Ir a la variable"
 
-#: src/ui/gui/data-editor.ui:448
-msgid "Data File _Comments"
-msgstr "_Comentarios al archivo de datos"
+#: src/ui/gui/data-editor.ui:459
+msgid "Data File _Comments..."
+msgstr "_Comentarios del Archivo de Datos..."
 
-#: src/ui/gui/data-editor.ui:454 src/ui/gui/output-viewer.ui:46
-#: src/ui/gui/syntax-editor.ui:135
+#: src/ui/gui/data-editor.ui:465 src/ui/gui/output-viewer.ui:47
+#: src/ui/gui/syntax-editor.ui:125
 msgid "_Windows"
 msgstr "_Ventanas"
 
-#: src/ui/gui/data-editor.ui:460 src/ui/gui/output-viewer.ui:52
-#: src/ui/gui/syntax-editor.ui:141
+#: src/ui/gui/data-editor.ui:471 src/ui/gui/output-viewer.ui:53
+#: src/ui/gui/syntax-editor.ui:131
 msgid "_Minimize All Windows"
 msgstr "_Minimizar todas las ventanas"
 
-#: src/ui/gui/data-editor.ui:466
+#: src/ui/gui/data-editor.ui:477
 msgid "_Split"
 msgstr "Dividir"
 
-#: src/ui/gui/data-editor.ui:642
+#: src/ui/gui/data-editor.ui:654
 msgid "Information Area"
 msgstr "Área de Información"
 
-#: src/ui/gui/data-editor.ui:664
+#: src/ui/gui/data-editor.ui:676
 msgid "Processor Area"
 msgstr "Área del procesador"
 
-#: src/ui/gui/data-editor.ui:689
+#: src/ui/gui/data-editor.ui:701
 msgid "Case Counter Area"
 msgstr "Área de Recuento"
 
-#: src/ui/gui/data-editor.ui:714
+#: src/ui/gui/data-editor.ui:726
 msgid "Filter Use Status Area"
 msgstr "Área de uso de Filtro"
 
-#: src/ui/gui/data-editor.ui:740
+#: src/ui/gui/data-editor.ui:752
 msgid "Weight Status Area"
 msgstr "Área de Ponderación"
 
-#: src/ui/gui/data-editor.ui:766
+#: src/ui/gui/data-editor.ui:778
 msgid "Split File Status Area"
 msgstr "Área de División de Archivo"
 
-#: src/ui/gui/output-viewer.ui:22
-msgid "_Export"
-msgstr "_Exportar"
+#: src/ui/gui/output-viewer.ui:16
+msgid "_Print..."
+msgstr "Im_primir..."
+
+#: src/ui/gui/output-viewer.ui:23
+msgid "_Export..."
+msgstr "_Exportar..."
 
-#: src/ui/gui/syntax-editor.ui:104
+#: src/ui/gui/syntax-editor.ui:94
 msgid "_Run"
 msgstr "Ejecuta_r"
 
-#: src/ui/gui/syntax-editor.ui:110
+#: src/ui/gui/syntax-editor.ui:100
 msgid "All"
 msgstr "Todos"
 
-#: src/ui/gui/syntax-editor.ui:116
+#: src/ui/gui/syntax-editor.ui:106
 msgid "Selection"
 msgstr "Selección"
 
-#: src/ui/gui/syntax-editor.ui:122
+#: src/ui/gui/syntax-editor.ui:112
 msgid "Current Line"
 msgstr "Línea actual"
 
-#: src/ui/gui/syntax-editor.ui:129
+#: src/ui/gui/syntax-editor.ui:119
 msgid "To End"
 msgstr "Hasta el final"
 
+#~ msgid "Scratch file handle %s has not yet been written, using SAVE or another procedure, so it cannot yet be used for reading."
+#~ msgstr "El manipulador de archivos de trabajo %s aún no se ha escrito, utilizando SAVE u otro procedimiento, de forma que aún no se puede leer."
+
+#~ msgid "scratch file"
+#~ msgstr "archivo de trabajo"
+
+#~ msgid "Variable suffix too large."
+#~ msgstr "Sufijo de la variable demasiado grande."
+
+#~ msgid "Missing space following `%c' at UTF-8 offset %zu in MRSETS record."
+#~ msgstr "Espacio perdido tras `%c' en la posición UTF-8 %zu del registro MRSETS."
+
+#~ msgid "Unexpected label source value `%s' following `E' at UTF-8 offset %zu in MRSETS record."
+#~ msgstr "Etiqueta de valor fuente inesperada `%s' tras 'E' en la posición UTF-8 %zu del registro MRSETS."
+
+#~ msgid "PSPP-data"
+#~ msgstr "datos-PSPP"
+
+#~ msgid "Syntax"
+#~ msgstr "Sintaxis"
+
+#~ msgid "%s %s PSPPIRE %s"
+#~ msgstr "%s %s PSPPIRE %s"
+
+#~ msgid "Untitled"
+#~ msgstr "Sin título"
+
 #~ msgid "column %d"
 #~ msgstr "columna %d"
 
@@ -7329,9 +7430,6 @@ msgstr "Hasta el final"
 #~ msgid "Sort Descending"
 #~ msgstr "Ordenación Descendente"
 
-#~ msgid "_Fonts"
-#~ msgstr "_Fuentes"
-
 #~ msgid "Buttons"
 #~ msgstr "Botones"
 
@@ -7772,9 +7870,6 @@ msgstr "Hasta el final"
 #~ msgid "_About"
 #~ msgstr "Sobre..."
 
-#~ msgid "Print"
-#~ msgstr "Imprimir"
-
 #~ msgid "Recall"
 #~ msgstr "Regresar"
 
@@ -7784,9 +7879,6 @@ msgstr "Hasta el final"
 #~ msgid "Redo"
 #~ msgstr "Rehacer"
 
-#~ msgid "Find"
-#~ msgstr "Buscar"
-
 #~ msgid "Use Sets"
 #~ msgstr "Utilizar conjuntos"
 
index 76742cab23ceb8fbc7767c350fb57fc60a1486ea..84db07f4e2d7440c06b23682a74db0b098eed79b 100644 (file)
--- a/po/lt.po
+++ b/po/lt.po
@@ -8,7 +8,7 @@ msgstr ""
 "Project-Id-Version: pspp-0.7.8\n"
 "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
 "POT-Creation-Date: 2011-05-04 06:57-0700\n"
-"PO-Revision-Date: 2011-05-05 11:11+0300\n"
+"PO-Revision-Date: 2011-07-20 21:10+0300\n"
 "Last-Translator: Mindaugas Baranauskas <embar@users.berlios.de>\n"
 "Language-Team: Lithuanian <komp_lt@konferencijos.lt>\n"
 "Language: lt\n"
@@ -313,39 +313,39 @@ msgstr "Formato %s negalima naudoti įvedimui."
 #: src/data/format.c:336
 #, c-format
 msgid "%s specifies width %d, but %s requires an even width."
-msgstr "%s nurodo %d ilgį, bet %s turėtų būti lyginio ilgio."
+msgstr "%s nurodo %d plotį, bet %s turėtų būti lyginio pločio."
 
 #: src/data/format.c:345
 #, c-format
 msgid "%s %s specifies width %d, but %s requires a width between %d and %d."
-msgstr "%s %s nurodo %d ilgį, bet %s turėtų būti nuo %d iki %d ilgio."
+msgstr "%s %s nurodo %d plotį, bet %s turėtų būti nuo %d iki %d pločio."
 
 #: src/data/format.c:354
 #, c-format
 msgid "%s %s specifies %d decimal place, but %s does not allow any decimals."
 msgid_plural "%s %s specifies %d decimal places, but %s does not allow any decimals."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%s %s nurodo %d dešimtainę skiltį, bet %s neleidžia naudoti dešimtainių skilčių."
+msgstr[1] "%s %s nurodo %d dešimtainę skiltį, bet %s neleidžia naudoti dešimtainių skilčių."
+msgstr[2] "%s %s nurodo %d dešimtaines skiltis, bet %s neleidžia naudoti dešimtainių skilčių."
+msgstr[3] "%s %s nurodo %d dešimtainių skilčių, bet %s neleidžia naudoti dešimtainių skilčių."
 
 #: src/data/format.c:365
 #, c-format
 msgid "%s %s specifies %d decimal place, but the given width allows at most %d decimals."
 msgid_plural "%s %s specifies %d decimal places, but the given width allows at most %d decimals."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%s %s nurodo %d dešimtainę skiltį, bet nurodytas plotis leistų iki %d skaitmenų po kablelio."
+msgstr[1] "%s %s nurodo %d dešimtainę skiltį, bet nurodytas plotis leistų iki %d skaitmenų po kablelio."
+msgstr[2] "%s %s nurodo %d dešimtaines skiltis, bet nurodytas plotis leistų iki %d skaitmenų po kablelio."
+msgstr[3] "%s %s nurodo %d dešimtainių skilčių, bet nurodytas plotis leistų iki %d skaitmenų po kablelio."
 
 #: src/data/format.c:372
 #, c-format
 msgid "%s %s specifies %d decimal place, but the given width does not allow for any decimals."
 msgid_plural "%s %s specifies %d decimal places, but the given width does not allow for any decimals."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%s %s nurodo %d dešimtainę skiltį, bet nurodytas plotis neleistų naudoti dešimtainių skilčių."
+msgstr[1] "%s %s nurodo %d dešimtainę skiltį, bet nurodytas plotis neleistų naudoti dešimtainių skilčių."
+msgstr[2] "%s %s nurodo %d dešimtaines skiltis, bet nurodytas plotis neleistų naudoti dešimtainių skilčių."
+msgstr[3] "%s %s nurodo %d dešimtainių skilčių, bet nurodytas plotis neleistų naudoti dešimtainių skilčių."
 
 #: src/data/format.c:411
 #, c-format
@@ -388,8 +388,9 @@ msgid "String variable with width %d is not compatible with format %s."
 msgstr "Teksto eilutės kintamasis, kurio plotis %d, yra nesuderinamas su %s formatu."
 
 #: src/data/gnumeric-reader.c:36
+#, fuzzy
 msgid "Support for Gnumeric files was not compiled into this installation of PSPP"
-msgstr "Gnumeric rinkmenų palaikymas nebuvo sukonfigūruotas šioje PSPP kompiliacijoje"
+msgstr "%s rinkmenų palaikymas nebuvo sukonfigūruotas kompiliuojant PSPP"
 
 #: src/data/gnumeric-reader.c:363
 #, c-format
@@ -423,7 +424,7 @@ msgstr "„%s“ negali būti naudojamas kaip identifikatorius, nes šis žodis
 #: src/data/identifier2.c:103
 #, c-format
 msgid "`%s' may not be used as an identifier because it contains ill-formed UTF-8 at byte offset %tu."
-msgstr ""
+msgstr "„%s“ negali būti identifikatoriumi, nes jame yra blogai suformuotas UTF-8 ties baitų poslinkiu %tu."
 
 #: src/data/identifier2.c:114
 #, c-format
@@ -515,7 +516,7 @@ msgstr "Tikėtasi skaičiaus."
 
 #: src/data/por-file-reader.c:414
 msgid "Missing numeric terminator."
-msgstr ""
+msgstr "Trūksta skaitmeninio terminatoriaus."
 
 #: src/data/por-file-reader.c:437
 msgid "Invalid integer."
@@ -549,17 +550,17 @@ msgstr "Netinkamas laiko ilgis %zu."
 #: src/data/por-file-reader.c:601
 #, c-format
 msgid "%s: Bad format specifier byte (%d).  Variable will be assigned a default format."
-msgstr ""
+msgstr "%s: Blogas formatą nurodantis baitas (%d). Kintamajam bus priskirtas numatytasis formatas."
 
 #: src/data/por-file-reader.c:622
 #, c-format
 msgid "Numeric variable %s has invalid format specifier %s."
-msgstr ""
+msgstr "Skaitmeniniam kintamajam %s nurodytas netinkamas formatas %s."
 
 #: src/data/por-file-reader.c:626
 #, c-format
 msgid "String variable %s with width %d has invalid format specifier %s."
-msgstr ""
+msgstr "Tekstiniam kintamajam %s, kurio plotis %d, nurodytas netinkamas formatas %s."
 
 #: src/data/por-file-reader.c:650
 msgid "Expected variable count record."
@@ -573,7 +574,7 @@ msgstr "Netinkamas kintamųjų skaičius %d."
 #: src/data/por-file-reader.c:663
 #, c-format
 msgid "Weight variable name (%s) truncated."
-msgstr ""
+msgstr "Svėrimo kintamojo vardas (%s) sutrumpintas."
 
 #: src/data/por-file-reader.c:678
 msgid "Expected variable record."
@@ -582,7 +583,7 @@ msgstr "Tikėtasi kintamojo įrašo."
 #: src/data/por-file-reader.c:682
 #, c-format
 msgid "Invalid variable width %d."
-msgstr "Netinkamas kintamojo ilgis %d."
+msgstr "Netinkamas kintamojo plotis %d."
 
 #: src/data/por-file-reader.c:690
 #, c-format
@@ -602,7 +603,7 @@ msgstr "Besikartojantis kintamojo vardas %s ties %d padėtimi pakeistas į %s."
 #: src/data/por-file-reader.c:757
 #, c-format
 msgid "Weighting variable %s not present in dictionary."
-msgstr ""
+msgstr "Svėrimo kintamojo %s žodyne nėra."
 
 #: src/data/por-file-reader.c:801
 #, c-format
@@ -795,9 +796,9 @@ msgid "Unknown variable format %<PRIu8>."
 msgstr "Nežinomas kintamojo formatas %<PRIu8>."
 
 #: src/data/sys-file-reader.c:1077
-#, c-format
+#, fuzzy, c-format
 msgid "%s variable %s has invalid %s format %s."
-msgstr "%s kintamasis %s yra netinkamo %s formato %s."
+msgstr "Skaitmeniniam kintamajam %s nurodytas netinkamas formatas %s."
 
 #: src/data/sys-file-reader.c:1080
 msgid "print"
@@ -1003,12 +1004,12 @@ msgstr "Žodyno įrašas nurodo į nežinomą kintamąjį %s."
 #: src/data/sys-file-reader.c:2411
 #, c-format
 msgid "Expecting digit at offset %zu in MRSETS record."
-msgstr ""
+msgstr "MRSETS įraše ties %zu poslinkiu tikimasi rasti skaičių."
 
 #: src/data/sys-file-reader.c:2419
 #, c-format
 msgid "Expecting space at offset %zu in MRSETS record."
-msgstr ""
+msgstr "MRSETS įraše ties %zu poslinkiu tikimasi rasti tarpą."
 
 #: src/data/sys-file-reader.c:2427
 #, c-format
@@ -1467,12 +1468,12 @@ msgstr ""
 #: src/language/control/repeat.c:115
 #, c-format
 msgid "Dummy variable name `%s' hides dictionary variable `%s'."
-msgstr ""
+msgstr "Fiktyvusis kintamojo vardas „%s“ slepia žodyno kintamąjį „%s“."
 
 #: src/language/control/repeat.c:119
 #, c-format
 msgid "Dummy variable name `%s' is given twice."
-msgstr ""
+msgstr "Fiktyvusis kintamasis vardas „%s“ pateiktas du kartus."
 
 #: src/language/control/repeat.c:162
 #, c-format
@@ -1502,7 +1503,7 @@ msgstr ""
 
 #: src/language/dictionary/attributes.c:104
 msgid "Attribute array index must be between 1 and 65535."
-msgstr ""
+msgstr "Atributo masyvo rodyklė turi būti tarp 1 ir 65535."
 
 #: src/language/dictionary/attributes.c:200
 #: src/language/data-io/get-data.c:324 src/language/data-io/get-data.c:362
@@ -1524,15 +1525,15 @@ msgstr ""
 
 #: src/language/dictionary/apply-dictionary.c:110
 msgid "No matching variables found between the source and target files."
-msgstr ""
+msgstr "Tarp šaltinio ir paskirties rinkmenų nerasta atitinkančių kintamųjų."
 
 #: src/language/dictionary/delete-variables.c:40
 msgid "DELETE VARIABLES may not be used after TEMPORARY.  Temporary transformations will be made permanent."
-msgstr ""
+msgstr "DELETE VARIABLES negali būti po TEMPORARY.  Laikinos transformacijos bus atliekamos kaip ilgalaikės."
 
 #: src/language/dictionary/delete-variables.c:47
 msgid "DELETE VARIABLES may not be used to delete all variables from the active dataset dictionary.  Use NEW FILE instead."
-msgstr ""
+msgstr "DELETE VARIABLES komandos negalima naudoti visų kintamųjų šalinimui iš veikiamojo duomenų rinkinio.  Verčiau naudokite NEW FILE."
 
 #: src/language/dictionary/formats.c:87
 msgid "`(' expected after variable list."
@@ -1559,7 +1560,7 @@ msgstr ""
 
 #: src/language/dictionary/modify-variables.c:91
 msgid "MODIFY VARS may not be used after TEMPORARY.  Temporary transformations will be made permanent."
-msgstr ""
+msgstr "MODIFY VARS negali būti po TEMPORARY.  Laikinos transformacijos bus atliekamos kaip ilgalaikės."
 
 #: src/language/dictionary/modify-variables.c:113
 #: src/language/dictionary/modify-variables.c:177
@@ -1630,7 +1631,7 @@ msgstr "Skaitmeninė reikšmė (VALUE) turi būti sveikasis skaičius."
 #: src/language/dictionary/mrsets.c:224
 #, c-format
 msgid "Required %s specification missing from %s subcommand."
-msgstr ""
+msgstr "Trūksta reikiamos %s specifikacijos pokomandžiui %s."
 
 #: src/language/dictionary/mrsets.c:232 src/language/dictionary/mrsets.c:270
 #, c-format
@@ -1760,7 +1761,7 @@ msgstr "Formato %s tipas negali būti naudojamas su teksto eilutės kintamuoju."
 
 #: src/language/dictionary/rename-variables.c:48
 msgid "RENAME VARS may not be used after TEMPORARY.  Temporary transformations will be made permanent."
-msgstr ""
+msgstr "RENAME VARS negali būti po TEMPORARY.  Laikinos transformacijos bus atliekamos kaip ilgalaikės."
 
 #: src/language/dictionary/rename-variables.c:58
 msgid "`(' expected."
@@ -1828,7 +1829,7 @@ msgstr "Nežinoma"
 
 #: src/language/dictionary/sys-file-info.c:111
 msgid "Real Format:"
-msgstr ""
+msgstr "Realus formatas:"
 
 #: src/language/dictionary/sys-file-info.c:113
 msgid "IEEE 754 LE."
@@ -1923,7 +1924,7 @@ msgstr "Nėra rodytinų kintamųjų."
 
 #: src/language/dictionary/sys-file-info.c:288
 msgid "Macros not supported."
-msgstr ""
+msgstr "Makrokomandos nepalaikomos."
 
 #: src/language/dictionary/sys-file-info.c:297
 msgid "The active dataset dictionary does not contain any documents."
@@ -2077,7 +2078,7 @@ msgstr ""
 
 #: src/language/utilities/host.c:102
 msgid "Interactive shell not supported on this platform."
-msgstr ""
+msgstr "Šioje platformoje interaktyvus apvalkalas nepalaikomas."
 
 #: src/language/utilities/host.c:114
 msgid "Command shell not supported on this platform."
@@ -2254,12 +2255,12 @@ msgstr ""
 #: src/language/stats/autorecode.c:128
 #, c-format
 msgid "Source variable count (%zu) does not match target variable count (%zu)."
-msgstr ""
+msgstr "Šaltinio kintamųjų kiekis (%zu) neatitinka paskirties kintamojo kiekio (%zu)."
 
 #: src/language/stats/autorecode.c:140
 #, c-format
 msgid "Target variable %s duplicates existing variable %s."
-msgstr ""
+msgstr "Paskirties kintamasis %s dubliuoja esamą kintamąjį %s."
 
 #: src/language/stats/binomial.c:136
 #, c-format
@@ -2357,7 +2358,7 @@ msgstr "Kriterijaus statistika"
 #: src/language/stats/chisquare.c:263 src/language/stats/friedman.c:282
 #: src/language/stats/kruskal-wallis.c:313
 msgid "Chi-Square"
-msgstr "Chi-kvadratas"
+msgstr "Chi kvadratas"
 
 #: src/language/stats/chisquare.c:264 src/language/stats/cochran.c:217
 #: src/language/stats/friedman.c:285 src/language/stats/kruskal-wallis.c:316
@@ -2389,7 +2390,7 @@ msgstr "Nesėkmė (%g)"
 
 #: src/language/stats/cochran.c:214
 msgid "Cochran's Q"
-msgstr "Cochran Q"
+msgstr "Kokrano Q"
 
 #: src/language/stats/correlations.c:97 src/language/stats/factor.c:1724
 #: src/language/stats/npar-summary.c:109
@@ -2628,7 +2629,7 @@ msgstr ""
 
 #: src/language/stats/factor.c:1695
 msgid "The dataset contains no complete observations. No analysis will be performed."
-msgstr ""
+msgstr "Duomenų rinkinyje nėra užbaigtų stebėjimų. Analizė nevykdysima."
 
 #: src/language/stats/factor.c:1747
 msgid "Analysis N"
@@ -2660,11 +2661,11 @@ msgstr "Pasukta faktorių matrica"
 
 #: src/language/stats/flip.c:99
 msgid "FLIP ignores TEMPORARY.  Temporary transformations will be made permanent."
-msgstr ""
+msgstr "FLIP nepaiso TEMPORARY.  Laikinos transformacijos bus atliekamos kaip ilgalaikės."
 
 #: src/language/stats/flip.c:151
 msgid "Could not create temporary file for FLIP."
-msgstr ""
+msgstr "FLIP komandai nepavyksta sukurti laikinosios rinkmenos."
 
 #: src/language/stats/flip.c:326
 #, c-format
@@ -2673,7 +2674,7 @@ msgstr ""
 
 #: src/language/stats/flip.c:333
 msgid "Error creating FLIP source file."
-msgstr ""
+msgstr "Klaida kuriant FLIP šaltinio rinkmeną."
 
 #: src/language/stats/flip.c:346
 #, c-format
@@ -2687,12 +2688,12 @@ msgstr "Netikėta skaitomos FLIP rinkmenos pabaiga."
 #: src/language/stats/flip.c:364
 #, c-format
 msgid "Error seeking FLIP source file: %s."
-msgstr ""
+msgstr "Klaida ieškant FLIP šaltinio rinkmenos: %s."
 
 #: src/language/stats/flip.c:372
 #, c-format
 msgid "Error writing FLIP source file: %s."
-msgstr ""
+msgstr "Klaida rašant FLIP šaltinio rinkmenos: %s."
 
 #: src/language/stats/flip.c:387
 #, c-format
@@ -2720,7 +2721,7 @@ msgstr "Vidutinis rangas"
 
 #: src/language/stats/friedman.c:279
 msgid "Kendall's W"
-msgstr "Kendall W"
+msgstr "Kendalo W"
 
 #: src/language/stats/mann-whitney.c:202 src/language/stats/wilcoxon.c:240
 msgid "Sum of Ranks"
@@ -2728,11 +2729,11 @@ msgstr "Rangų suma"
 
 #: src/language/stats/mann-whitney.c:264
 msgid "Mann-Whitney U"
-msgstr "Mann-Whitney U"
+msgstr "Mano ir Vitnio U"
 
 #: src/language/stats/mann-whitney.c:265
 msgid "Wilcoxon W"
-msgstr "Wilcoxon W"
+msgstr "Vilkoksono W"
 
 #: src/language/stats/mann-whitney.c:266 src/language/stats/runs.c:396
 #: src/language/stats/wilcoxon.c:317
@@ -2807,7 +2808,7 @@ msgstr "Kontrastų koeficientų skaičius turi būti lygus grupių skaičiui"
 #: src/language/stats/oneway.c:551
 #, c-format
 msgid "Coefficients for contrast %zu do not total zero"
-msgstr ""
+msgstr "Kontrastų sąrašo Nr. %zu suma koeficientų suma nelygi nuliui"
 
 #: src/language/stats/oneway.c:592 src/language/stats/regression.q:285
 msgid "Sum of Squares"
@@ -2825,7 +2826,7 @@ msgstr "F"
 #: src/language/stats/oneway.c:596 src/language/stats/oneway.c:841
 #: src/language/stats/regression.q:203 src/language/stats/regression.q:289
 msgid "Significance"
-msgstr "Reikšmingumo lygmuo"
+msgstr "Reikšmingumas"
 
 #: src/language/stats/oneway.c:614
 msgid "Between Groups"
@@ -2917,11 +2918,11 @@ msgstr "Klasterių skaičius negali būti didesnis nei atvejų skaičius."
 
 #: src/language/stats/quick-cluster.c:411
 msgid "Final Cluster Centers"
-msgstr ""
+msgstr "Galutiniai klasterių centrai"
 
 #: src/language/stats/quick-cluster.c:415
 msgid "Initial Cluster Centers"
-msgstr ""
+msgstr "Pradiniai klasterių centrai"
 
 #: src/language/stats/quick-cluster.c:418
 #: src/language/stats/quick-cluster.c:472
@@ -2981,7 +2982,7 @@ msgstr "Koreguota „elementas-visuma“ koreliacija"
 
 #: src/language/stats/reliability.c:614
 msgid "Cronbach's Alpha if Item Deleted"
-msgstr "Cronbacho alfa, jei elementas pašalintas"
+msgstr "Kronbacho alfa, jei elementas pašalintas"
 
 #: src/language/stats/reliability.c:688
 msgid "Reliability Statistics"
@@ -2989,7 +2990,7 @@ msgstr "Klausimynų patikimumo statistika"
 
 #: src/language/stats/reliability.c:728 src/language/stats/reliability.c:747
 msgid "Cronbach's Alpha"
-msgstr "Cronbacho alfa"
+msgstr "Kronbacho alfa"
 
 #: src/language/stats/reliability.c:731 src/language/stats/reliability.c:756
 #: src/language/stats/reliability.c:767
@@ -3014,7 +3015,7 @@ msgstr "Koreliacija tarp formų"
 
 #: src/language/stats/reliability.c:779
 msgid "Spearman-Brown Coefficient"
-msgstr "Spearman-Brown koeficientas"
+msgstr "Spirmeno ir Brauno koeficientas"
 
 #: src/language/stats/reliability.c:782
 msgid "Equal Length"
@@ -3026,7 +3027,7 @@ msgstr "Nevienodas ilgis"
 
 #: src/language/stats/reliability.c:789
 msgid "Guttman Split-Half Coefficient"
-msgstr "Guttman dalinimo pusiau koeficientas"
+msgstr "Gutmano dalinimo pusiau koeficientas"
 
 #: src/language/stats/roc.c:955
 msgid "Area Under the Curve"
@@ -3224,7 +3225,7 @@ msgstr "Derinamos rinkmenos su nesuderinamomis koduotėmis. Tekstinių eilučių
 #: src/language/data-io/combine-files.c:555
 #, c-format
 msgid "Variable %s in file %s has different type or width from the same variable in earlier file."
-msgstr "Kintamasis %s rinkmenoje %s yra kitokio tipo arba kitokio ilgio negu tas pats kintamasis ankstesnėje rinkmenoje."
+msgstr "Kintamasis %s rinkmenoje %s yra kitokio tipo arba kitokio pločio negu tas pats kintamasis ankstesnėje rinkmenoje."
 
 #: src/language/data-io/combine-files.c:561
 #, c-format
@@ -4121,7 +4122,7 @@ msgstr ""
 "  -r, --no-statrc           paleidžiant uždrausti veikiančią rc rinkmeną\n"
 "  -a, --algorithm={compatible|enhanced}\n"
 "                            nustatykite „compatible“, jei norite rezultatų,\n"
-"                            suskaičiuotų naudojant prastesnius algoritmus\n"
+"                            apskaičiuotų naudojant prastesnius algoritmus\n"
 "  -x, --syntax={compatible|enhanced}\n"
 "                            rinkdamiesi „compatible“ uždrausite PSPP papildinius\n"
 "  -i, --interactive         sintaksę interpretuoti interaktyvioje veiksenoje\n"
@@ -4174,7 +4175,7 @@ msgstr "Phi"
 
 #: src/ui/gui/crosstabs-dialog.c:42
 msgid "CC"
-msgstr "CC"
+msgstr "Konting.k."
 
 #: src/ui/gui/crosstabs-dialog.c:43 src/language/stats/crosstabs.q:1944
 msgid "Lambda"
@@ -4182,7 +4183,7 @@ msgstr "Liambda"
 
 #: src/ui/gui/crosstabs-dialog.c:44
 msgid "UC"
-msgstr "Neap.k."
+msgstr "Neapibr.k."
 
 #: src/ui/gui/crosstabs-dialog.c:45
 msgid "BTau"
@@ -4347,7 +4348,7 @@ msgstr ""
 "  -I-, --no-include         išvalyti paieškos kelią\n"
 "  -a, --algorithm={compatible|enhanced}\n"
 "                            nustatykite „compatible“, jei norite rezultatų,\n"
-"                            suskaičiuotų naudojant prastesnius algoritmus\n"
+"                            apskaičiuotų naudojant prastesnius algoritmus\n"
 "  -x, --syntax={compatible|enhanced}\n"
 "                            rinkdamiesi „compatible“ uždrausite PSPP papildinius\n"
 "  -i, --interactive         sintaksę interpretuoti interaktyvioje veiksenoje\n"
@@ -4461,7 +4462,7 @@ msgstr "Šrifto pasirinkimas"
 #. TRANSLATORS: This will form a filename.  Please avoid whitespace.
 #: src/ui/gui/psppire-data-window.c:1287
 msgid "Data Editor"
-msgstr "Duomenų redaktorius"
+msgstr "duomenų redaktorius"
 
 #. TRANSLATORS: This string must be a valid variable name.  That means:
 #. - The string must be at most 64 bytes (not characters) long.
@@ -4477,7 +4478,7 @@ msgstr "Kint%05d"
 
 #: src/ui/gui/psppire-output-window.c:467
 msgid "Infer file type from extension"
-msgstr "Rinkmenos tipą nuspėti pagal prievardį"
+msgstr "rinkmenos tipą nuspėti pagal prievardį"
 
 #: src/ui/gui/psppire-output-window.c:468
 msgid "PDF (*.pdf)"
@@ -4493,11 +4494,11 @@ msgstr "OpenDocument (*.odt)"
 
 #: src/ui/gui/psppire-output-window.c:471
 msgid "Text (*.txt)"
-msgstr "Tekstinės rinkmenos (*.txt)"
+msgstr "tekstinės rinkmenos (*.txt)"
 
 #: src/ui/gui/psppire-output-window.c:472
 msgid "PostScript (*.ps)"
-msgstr "Postskriptinės rinkmenos (*.ps)"
+msgstr "postskriptinės rinkmenos (*.ps)"
 
 #: src/ui/gui/psppire-output-window.c:473
 msgid "Comma-Separated Values (*.csv)"
@@ -4518,7 +4519,7 @@ msgstr "Rezultatai"
 
 #: src/ui/gui/psppire-output-window.c:1060
 msgid "Output Viewer"
-msgstr "Rezultatų peržiūra"
+msgstr "rezultatų peržiūra"
 
 #: src/ui/gui/psppire-syntax-window.c:475
 #, c-format
@@ -4531,12 +4532,12 @@ msgstr "Įrašyti sintaksę"
 
 #: src/ui/gui/psppire-syntax-window.c:502 src/ui/gui/psppire-window.c:775
 msgid "Syntax Files (*.sps) "
-msgstr "Sintaksės rinkmenos (*.sps)"
+msgstr "sintaksės rinkmenos (*.sps)"
 
 #. TRANSLATORS: This will form a filename.  Please avoid whitespace.
 #: src/ui/gui/psppire-syntax-window.c:733
 msgid "Syntax Editor"
-msgstr "Sintaksės redaktorius"
+msgstr "sintaksės redaktorius"
 
 #: src/ui/gui/psppire-syntax-window.c:747
 #, c-format
@@ -4551,7 +4552,7 @@ msgstr "Tipas"
 #: src/ui/gui/psppire-var-sheet.c:536 src/ui/gui/psppire-var-store.c:835
 #: src/ui/gui/compute.ui:517
 msgid "Width"
-msgstr "Ilgis"
+msgstr "Plotis"
 
 #: src/ui/gui/psppire-var-sheet.c:537 src/ui/gui/psppire-var-store.c:836
 msgid "Decimals"
@@ -4640,7 +4641,7 @@ msgstr "Naujas"
 
 #: src/ui/gui/recode-dialog.c:918 src/ui/gui/recode-dialog.c:991
 msgid "Old"
-msgstr "Sena"
+msgstr "Senas"
 
 #: src/ui/gui/recode-dialog.c:1236
 msgid "Recode into Different Variables: Old and New Values "
@@ -4831,24 +4832,24 @@ msgid "Unrecognized record type 7, subtype %d."
 msgstr "Įrašo tipas 7, potipis %d neatpažintas."
 
 #: tests/dissect-sysfile.c:595
-#, c-format
+#, fuzzy, c-format
 msgid "Bad size (%zu) or count (%zu) field on record type 7, subtype 3."
-msgstr ""
+msgstr "Įrašo tipas 7, potipis %d neatpažintas."
 
 #: tests/dissect-sysfile.c:626
-#, c-format
+#, fuzzy, c-format
 msgid "Bad size (%zu) or count (%zu) on extension 4."
-msgstr ""
+msgstr "11-to plėtinio blogas dydis %zu."
 
 #: tests/dissect-sysfile.c:692
-#, c-format
+#, fuzzy, c-format
 msgid "Missing space following `%c' at offset %zu in MRSETS record"
-msgstr ""
+msgstr "MRSETS įraše ties %zu poslinkiu tikimasi rasti tarpą."
 
 #: tests/dissect-sysfile.c:701
-#, c-format
+#, fuzzy, c-format
 msgid "Unexpected label source value `%s' following `E' at offset %zu in MRSETS record"
-msgstr ""
+msgstr "MRSETS įraše ties %zu poslinkiu tikimasi rasti skaičių."
 
 #: tests/dissect-sysfile.c:759
 #, c-format
@@ -4866,9 +4867,9 @@ msgid "%s: Attribute value %s[%d] is not quoted: %s"
 msgstr "%s: Atributo reikšmė %s[%d] be kabučių: %s"
 
 #: tests/dissect-sysfile.c:881
-#, c-format
+#, fuzzy, c-format
 msgid "Bad size %zu for extended number of cases."
-msgstr ""
+msgstr "11-to plėtinio blogas dydis %zu."
 
 #: tests/dissect-sysfile.c:887
 #, c-format
@@ -5004,7 +5005,7 @@ msgstr "Procentai"
 #: src/language/stats/crosstabs.q:936
 #, c-format
 msgid "Crosstabulation %s contained no non-missing cases."
-msgstr "Požymių dažnių lentelėje „%s“ visi atvejai turi praleistas reikšmes."
+msgstr "Požymių priklausomumo lentelėje „%s“ visi atvejai turi praleistas reikšmes."
 
 #: src/language/stats/crosstabs.q:1134
 msgid "count"
@@ -5571,12 +5572,12 @@ msgstr ""
 #: src/language/data-io/list.q:106
 #, c-format
 msgid "The first case (%ld) to list is less than 1.  The value is being reset to 1."
-msgstr ""
+msgstr "Pirmasis atvejis (%ld) mažesnis už 1. Reikšmė pakeista į 1."
 
 #: src/language/data-io/list.q:112
 #, c-format
 msgid "The last case (%ld) to list is less than 1.  The value is being reset to 1."
-msgstr ""
+msgstr "Paskutinysis atvejis (%ld) mažesnis už 1. Reikšmė pakeista į 1."
 
 #: src/language/data-io/list.q:118
 #, c-format
@@ -5710,7 +5711,7 @@ msgstr "Pirso_no"
 
 #: src/ui/gui/correlation.ui:123
 msgid "_Kendall's tau-b"
-msgstr "_Kendall tau-b"
+msgstr "_Kendalo tau-b"
 
 #: src/ui/gui/correlation.ui:138
 msgid "_Spearman"
@@ -5738,7 +5739,7 @@ msgstr "_Pažymėti reikšmingas koreliacijas"
 
 #: src/ui/gui/crosstabs.ui:7
 msgid "Crosstabs"
-msgstr "Požymių dažnių lentelės"
+msgstr "Požymių priklausomumo lentelės"
 
 #: src/ui/gui/crosstabs.ui:50
 msgid "Rows"
@@ -5759,7 +5760,7 @@ msgstr "Langeliai..."
 
 #: src/ui/gui/crosstabs.ui:227
 msgid "Crosstabs: Format"
-msgstr "Požymių dažnių lentelės: formatas"
+msgstr "Požymių priklausomumo lentelės: formatas"
 
 #: src/ui/gui/crosstabs.ui:241
 msgid "Print tables"
@@ -5787,7 +5788,7 @@ msgstr "Etikečių uždėjimas"
 
 #: src/ui/gui/crosstabs.ui:369
 msgid "Crosstabs: Cells"
-msgstr "Požymių dažnių lentelės: langeliai"
+msgstr "Požymių priklausomumo lentelės: langeliai"
 
 #: src/ui/gui/crosstabs.ui:402
 msgid "Cell Display"
@@ -5795,7 +5796,7 @@ msgstr "Rodytini langeliai"
 
 #: src/ui/gui/crosstabs.ui:430
 msgid "Crosstabs: Statistics"
-msgstr "Požymių dažnių lentelės: statistika"
+msgstr "Požymių priklausomumo lentelės: statistika"
 
 #: src/ui/gui/crosstabs.ui:463 src/ui/gui/oneway.ui:222
 #: src/ui/gui/regression.ui:340
@@ -6160,15 +6161,15 @@ msgstr "_Kriterijaus kintamieji:"
 
 #: src/ui/gui/k-related.ui:122
 msgid "_Friedman"
-msgstr "Friedman"
+msgstr "_Fridmano"
 
 #: src/ui/gui/k-related.ui:136
 msgid "_Kendall's W"
-msgstr "Kendall W"
+msgstr "_Kendalo W"
 
 #: src/ui/gui/k-related.ui:150
 msgid "_Cochran's Q"
-msgstr "Cochran Q"
+msgstr "_Kokrano Q"
 
 #: src/ui/gui/k-related.ui:169
 msgid "Test Type"
@@ -6224,7 +6225,7 @@ msgstr "Atvejus sverti pagal"
 
 #: src/ui/gui/psppire.ui:102
 msgid "Frequency Variable"
-msgstr "Dažnių kintamasis"
+msgstr "dažnių kintamąjį"
 
 #: src/ui/gui/psppire.ui:145
 msgid "Current Status: "
@@ -6232,7 +6233,7 @@ msgstr "Dabartinė būsena: "
 
 #: src/ui/gui/psppire.ui:195
 msgid "Transpose"
-msgstr "Perstatyti"
+msgstr "Transponuoti"
 
 #: src/ui/gui/psppire.ui:247
 msgid "Name Variable:"
@@ -6472,7 +6473,7 @@ msgstr "Išvedami kintamieji yra teksto eilutės. "
 
 #: src/ui/gui/recode.ui:629
 msgid "Width: "
-msgstr "Ilgis: "
+msgstr "Plotis: "
 
 #: src/ui/gui/recode.ui:757
 msgid "(optional case selection condition)"
@@ -6830,7 +6831,7 @@ msgstr "Imtis"
 
 #: src/ui/gui/var-sheet-dialogs.ui:294
 msgid "Width:"
-msgstr "Ilgis:"
+msgstr "Plotis:"
 
 #: src/ui/gui/var-sheet-dialogs.ui:339
 msgid "Decimal Places:"
@@ -6973,7 +6974,7 @@ msgstr "_Ieškoti..."
 
 #: src/ui/gui/data-editor.ui:189
 msgid "_View"
-msgstr "Ro_dinys"
+msgstr "Ro_dymas"
 
 #: src/ui/gui/data-editor.ui:196
 msgid "_Status Bar"
@@ -7009,11 +7010,11 @@ msgstr "Rikiuoti veikiamojo duomenų rinkinio atvejus"
 
 #: src/ui/gui/data-editor.ui:252
 msgid "_Transpose..."
-msgstr "_Perstatyti..."
+msgstr "_Transponuoti..."
 
 #: src/ui/gui/data-editor.ui:253
 msgid "Transpose the cases with the variables"
-msgstr "Perstatyti atvejus ir kintamuosius"
+msgstr "Transponuoti atvejus ir kintamuosius"
 
 #: src/ui/gui/data-editor.ui:260
 msgid "_Aggregate..."
@@ -7045,7 +7046,7 @@ msgstr "Trans_formuoti"
 
 #: src/ui/gui/data-editor.ui:294
 msgid "_Compute..."
-msgstr "_Skaičiuoti..."
+msgstr "_Apskaičiuoti..."
 
 #: src/ui/gui/data-editor.ui:300
 msgid "Ran_k Cases..."
@@ -7081,7 +7082,7 @@ msgstr "_Tyrinėti..."
 
 #: src/ui/gui/data-editor.ui:355
 msgid "_Crosstabs..."
-msgstr "_Požymių dažnių lentelės..."
+msgstr "_Požymių priklausomumo lentelės..."
 
 #: src/ui/gui/data-editor.ui:361
 msgid "Compare _Means"
@@ -7221,6 +7222,302 @@ msgstr "Veikiamoji eilutė"
 msgid "To End"
 msgstr "Iki galo"
 
+#~| msgid "Error opening `%s' for reading as a Gnumeric file: %s."
+#~ msgid "Error opening `%s' for reading as a OpenDocument spreadsheet file: %s."
+#~ msgstr "Klaida skaitymui atveriant „%s“ kaip OpenDocument skaičialentės rinkmeną: %s."
+
+#~ msgid "Could not extract OpenDocument spreadsheet from file `%s': %s."
+#~ msgstr "Iš rinkmenos „%s“ nepavyksta ištraukti OpenDocument skaičialentės: %s."
+
+#~| msgid "%s variable %s has invalid %s format %s."
+#~ msgid "Variable %s with width %d has invalid print format 0x%x."
+#~ msgstr "%s kintamasis, kurio plotis %d, turi netinkamą spausdinimo formatą 0x%x."
+
+#~| msgid "String variable with width %d is not compatible with format %s."
+#~ msgid "Variable %s with width %d has invalid write format 0x%x."
+#~ msgstr "%s kintamasis, kurio plotis %d, turi netinkamą rašymo formatą 0x%x."
+
+#~| msgid "%s is not yet implemented."
+#~ msgid "Multivariate analysis is not yet implemented"
+#~ msgstr "Daugiamatė analizė dar nėra realizuota."
+
+#~| msgid "Only USE ALL is currently implemented."
+#~ msgid "Only type 3 sum of squares are currently implemented"
+#~ msgstr "Šiuo metu realizuota tik 3 tipo kvadratų suma"
+
+#~ msgid "/DESIGN is mandatory in GLM"
+#~ msgstr "/DESIGN būtinas komandai GLM"
+
+#~| msgid "Sum of Squares"
+#~ msgid "Type %s Sum of Squares"
+#~ msgstr "%s tipo kvadratų suma"
+
+#~ msgid "Corrected Model"
+#~ msgstr "Koreguotas modelis"
+
+#~| msgid "Percent"
+#~ msgid "Intercept"
+#~ msgstr "Atkarpa"
+
+#~ msgid "The McNemar test is appropriate only for dichotomous variables"
+#~ msgstr "Maknemaros kriterijus skirtas tik dichotominiams kintamiesiems"
+
+#~ msgid "LSD"
+#~ msgstr "LSD"
+
+#~| msgid "Tukey"
+#~ msgid "Tukey HSD"
+#~ msgstr "Tjukio HSD"
+
+#~ msgid "Bonferroni"
+#~ msgstr "Bonferroni"
+
+#~ msgid "Scheffé"
+#~ msgstr "Šefė"
+
+#~ msgid "Games-Howell"
+#~ msgstr "Games-Howell"
+
+#~ msgid "Šidák"
+#~ msgstr "Šidák"
+
+#~ msgid "The post hoc analysis method %s is not supported."
+#~ msgstr "Post hoc analizės medotas %s nepalaikomas."
+
+#~ msgid "In contrast list %zu, the number of coefficients (%d) does not equal the number of groups (%d). This contrast list will be ignored."
+#~ msgstr "Kontrastų sąraše Nr. %zu koeficientų skaičius (%d) nelygus grupių skaičiui (%d). Todėl šio kontrastų sąrašo nepaisoma."
+
+#~ msgid "Multiple Comparisons"
+#~ msgstr "Kartotiniai palyginimai"
+
+#~| msgid "95%% Confidence Interval"
+#~ msgid "%g%% Confidence Interval"
+#~ msgstr "%g%% pasikliautinasis intervalas"
+
+#~| msgid "Cases < Test Value"
+#~ msgid "Cases ≥ Test Value"
+#~ msgstr "Atvejai ≥ kriterijaus reikšmė"
+
+#~| msgid "%s - Page %d"
+#~ msgid "%s - %s"
+#~ msgstr "%s - %s"
+
+#~ msgid "Unsupported compression type (%d)"
+#~ msgstr "Nepalaikomas glaudinimo tipas (%d)"
+
+#~ msgid "Corrupt file at 0x%llx: Expected %<PRIx32>; got %<PRIx32>"
+#~ msgstr "Rinkmena sugadinta ties 0x%llx: tikėtasi %<PRIx32>; yra %<PRIx32>"
+
+#~ msgid "Cannot find central directory"
+#~ msgstr "Nepavyksta rasti centrinio katalogo"
+
+#~| msgid "failed to create temporary directory"
+#~ msgid "Failed to seek to end of central directory record: %s"
+#~ msgstr "Nepavyko rasti centrinio katalogo įrašo pabaigos: %s"
+
+#~| msgid "failed to create temporary directory"
+#~ msgid "Failed to seek to central directory: %s"
+#~ msgstr "Nepavyko rasti centrinio katalogo: %s"
+
+#~ msgid "Failed to seek to start of member `%s': %s"
+#~ msgstr "Nepavyko rasti „%s“ nario pradžios: %s"
+
+#~ msgid "Name mismatch in zip archive. Central directory says `%s'; local file header says `%s'"
+#~ msgstr "Zip archyve neatitinka vardai. Centrinis katalogas nurodo „%s“; vietinės rinkmenos antraštė nurodo „%s“"
+
+#~ msgid "Automatically Detect"
+#~ msgstr "Aptikti automatiškai"
+
+#~| msgid "Little Endian"
+#~ msgid "Locale Encoding"
+#~ msgstr "Lokalės koduotė"
+
+#~ msgid "Arabic"
+#~ msgstr "Arabų"
+
+#~ msgid "Armenian"
+#~ msgstr "Armėnų"
+
+#~ msgid "Baltic"
+#~ msgstr "Baltų"
+
+#~ msgid "Celtic"
+#~ msgstr "Keltų"
+
+#~ msgid "Central European"
+#~ msgstr "Centrinės Europos"
+
+#~ msgid "Chinese Simplified"
+#~ msgstr "Supaprastinta kinų"
+
+#~ msgid "Chinese Traditional"
+#~ msgstr "Tradicinė kinų"
+
+#~ msgid "Croatian"
+#~ msgstr "Kroatų"
+
+#~ msgid "Cyrillic"
+#~ msgstr "Kirilica"
+
+#~ msgid "Cyrillic/Russian"
+#~ msgstr "Kirilica / rusų"
+
+#~ msgid "Cyrillic/Ukrainian"
+#~ msgstr "Kirilica / ukrainiečių"
+
+#~ msgid "Georgian"
+#~ msgstr "Gruzinų"
+
+#~ msgid "Greek"
+#~ msgstr "Graikų"
+
+#~ msgid "Gujarati"
+#~ msgstr "Gudžarati"
+
+#~ msgid "Gurmukhi"
+#~ msgstr "Gurmukhi"
+
+#~ msgid "Hebrew"
+#~ msgstr "Hebrajų"
+
+#~ msgid "Hebrew Visual"
+#~ msgstr "Hebrajų regimoji"
+
+#~ msgid "Hindi"
+#~ msgstr "Hindi"
+
+#~ msgid "Icelandic"
+#~ msgstr "Islandų"
+
+#~ msgid "Japanese"
+#~ msgstr "Japonų"
+
+#~ msgid "Korean"
+#~ msgstr "Korėjiečių"
+
+#~ msgid "Nordic"
+#~ msgstr "Šiaurės"
+
+#~ msgid "Romanian"
+#~ msgstr "Rumunų"
+
+#~ msgid "South European"
+#~ msgstr "Pietų Europos"
+
+#~ msgid "Thai"
+#~ msgstr "Tajų"
+
+#~ msgid "Turkish"
+#~ msgstr "Turkų"
+
+#~ msgid "Vietnamese"
+#~ msgstr "Vietnamiečių"
+
+#~ msgid "Western European"
+#~ msgstr "Vakarų Europos"
+
+#~ msgid "Character Encoding: "
+#~ msgstr "Ženklų kodavimas: "
+
+#~ msgid "Message"
+#~ msgstr "Pranešimas"
+
+#~| msgid "Options"
+#~ msgid "_Options"
+#~ msgstr "Pa_rinktys"
+
+#~| msgid "Wilcoxon W"
+#~ msgid "_Wilcoxon"
+#~ msgstr "_Vilkoksono"
+
+#~ msgid "_Sign"
+#~ msgstr "_Ženklų"
+
+#~ msgid "_McNemar"
+#~ msgstr "_Maknemaros"
+
+#~| msgid "Paired Samples Test"
+#~ msgid "Two-Related-Samples Tests"
+#~ msgstr "Kriterijai dvejoms priklausomoms imtims"
+
+#~ msgid "Automatic Recode"
+#~ msgstr "Automatinis perkodavimas"
+
+#~| msgid "Variable Name: "
+#~ msgid "Variable -> New Name"
+#~ msgstr "Kintamasis -> Naujas vardas"
+
+#~| msgid "_Largest Value"
+#~ msgid "_Lowest value"
+#~ msgstr "_Mažiausios reikšmės"
+
+#~| msgid "_Largest Value"
+#~ msgid "_Highest value"
+#~ msgstr "_Didžiausios reikšmės"
+
+#~ msgid "Recode starting from"
+#~ msgstr "Perkodavimą pradėti nuo"
+
+#~| msgid "New Value"
+#~ msgid "_New Name"
+#~ msgstr "_Naujas vardas"
+
+#~ msgid "_Add New Name"
+#~ msgstr "Pri_dėti naują vardą"
+
+#~ msgid "_Use the same recoding scheme for all variables"
+#~ msgstr "_Visiems kintamiesiems naudoti tą pačią perkodavimo schemą"
+
+#~ msgid "Treat _blank string values as missing"
+#~ msgstr "_Tuščias reikšmes laikyti praleistomis"
+
+#~ msgid "Count Occurrences of Values within Cases"
+#~ msgstr "Suskaičiuoti atvejuose pasitaikančias reikšmes"
+
+#~| msgid "Name Variable:"
+#~ msgid "Numeric _Variables:"
+#~ msgstr "Skaitmeniniai _kintamieji:"
+
+#~| msgid "Target Variable:"
+#~ msgid "_Target Variable:"
+#~ msgstr "Pa_skirties kintamasis:"
+
+#~| msgid "Target Variable:"
+#~ msgid "Target _Label:"
+#~ msgstr "Paskirties _etiketė:"
+
+#~| msgid "_Weight Cases..."
+#~ msgid "_Define Values..."
+#~ msgstr "Apibrėžti _reikšmes..."
+
+#~ msgid "Count Values within Cases: Values to Count"
+#~ msgstr "Suskaičiuoti reikšmes atvejuose: suskaičiuotinos reikšmės"
+
+#~| msgid "Value of Contrast"
+#~ msgid "Values _to Count:"
+#~ msgstr "Suskaičiuotinos reikšmės"
+
+#~| msgid "Test Variable(s):"
+#~ msgid "Test _Pair(s):"
+#~ msgstr "_Pora(-os):"
+
+#~| msgid "_Font..."
+#~ msgid "Cou_nt..."
+#~ msgstr "_Suskaičiuoti reikšmių pasikartojimą..."
+
+#~ msgid "Auto_matic Recode..."
+#~ msgstr "Auto_matiškai perkoduoti..."
+
+#~| msgid "K Related _Samples..."
+#~ msgid "2 _Related Samples..."
+#~ msgstr "2 p_riklausomos imtys..."
+
+#~ msgid "Split"
+#~ msgstr "padalijimas"
+
+#~ msgid "Alpha"
+#~ msgstr "alfa"
+
 #~ msgid "Variable suffix too large."
 #~ msgstr "Kintamojo priesaga yra per ilga."
 
@@ -7275,12 +7572,6 @@ msgstr "Iki galo"
 #~ msgid "Unable to open `%s': %s."
 #~ msgstr "Nepavyksta atverti „%s“: %s."
 
-#~ msgid "Corrected Model"
-#~ msgstr "Koreguotas modelis"
-
-#~ msgid "Error"
-#~ msgstr "Klaida"
-
 #~ msgid "Analyse"
 #~ msgstr "Analizuoti"
 
@@ -7312,8 +7603,8 @@ msgstr "Iki galo"
 #~ "Alpha\n"
 #~ "Split"
 #~ msgstr ""
-#~ "Alpha\n"
-#~ "Dalinimas pusiau"
+#~ "alfa\n"
+#~ "padalijimas"
 
 #~ msgid "Asymp. Sig. (2-sided)"
 #~ msgstr "Asimp. p-reikšmė (2-pusė)"
@@ -7600,9 +7891,6 @@ msgstr "Iki galo"
 #~ msgid "error reading \"%s\""
 #~ msgstr "skaitymo klaida „%s“"
 
-#~ msgid "error writing \"%s\""
-#~ msgstr "įrašymo klaida „%s“"
-
 #~ msgid "Regresion: Statistics"
 #~ msgstr "Regresija: statistika"
 
index 81a9d9c5259bf87838cfe68260eb68eb28fa44d0..4385fd6d63055ead3ddba1836ba57f8aedbef006 100644 (file)
@@ -82,6 +82,8 @@ src_data_libdata_la_SOURCES = \
        src/data/make-file.h \
        src/data/mrset.c \
        src/data/mrset.h \
+       src/data/ods-reader.c \
+       src/data/ods-reader.h \
        src/data/por-file-reader.c \
        src/data/por-file-reader.h \
        src/data/por-file-writer.c \
@@ -94,6 +96,8 @@ src_data_libdata_la_SOURCES = \
        src/data/settings.h \
        src/data/short-names.c \
        src/data/short-names.h \
+       src/data/spreadsheet-reader.c \
+       src/data/spreadsheet-reader.h \
        src/data/subcase.c \
        src/data/subcase.h \
        src/data/sys-file-encoding.c \
index 2988d50295b073482b3bee10f274834a56bec6d0..5e4080b11f22ffa463f4bc0264b68de2736abd25 100644 (file)
@@ -33,6 +33,7 @@
 #include "libpspp/version.h"
 
 #include "gl/dirname.h"
+#include "gl/dosname.h"
 #include "gl/intprops.h"
 #include "gl/minmax.h"
 #include "gl/relocatable.h"
index e15931ad1a2b4764547747945e9399305f2b8946..3c407f4a85f3c0bb842e41a3cca37098b1a5850a 100644 (file)
@@ -500,6 +500,7 @@ fmt_resize (struct fmt_spec *fmt, int width)
 void
 fmt_fix (struct fmt_spec *fmt, bool for_input)
 {
+  unsigned int step;
   int min_w, max_w;
   int max_d;
 
@@ -511,18 +512,19 @@ fmt_fix (struct fmt_spec *fmt, bool for_input)
   else if (fmt->w > max_w)
     fmt->w = max_w;
 
-  /* First, if FMT has more decimal places than allowed, attempt
-     to increase FMT's width until that number of decimal places
-     can be achieved. */
-  if (fmt->d > fmt_max_decimals (fmt->type, fmt->w, for_input))
+  /* Round width to step. */
+  step = fmt_step_width (fmt->type);
+  fmt->w = ROUND_DOWN (fmt->w, step);
+
+  /* If FMT has more decimal places than allowed, attempt to increase FMT's
+     width until that number of decimal places can be achieved. */
+  if (fmt->d > fmt_max_decimals (fmt->type, fmt->w, for_input)
+      && fmt_takes_decimals (fmt->type))
     {
-      int w;
-      for (w = fmt->w; w <= max_w; w++)
-        if (fmt_max_decimals (fmt->type, w, for_input) >= fmt->d)
-          {
-            fmt->w = w;
-            break;
-          }
+      int max_w = fmt_max_width (fmt->type, for_input);
+      for (; fmt->w < max_w; fmt->w++)
+        if (fmt->d <= fmt_max_decimals (fmt->type, fmt->w, for_input))
+          break;
     }
 
   /* Clamp decimals to those allowed by format and width. */
index 61fbab899b8bd44eff63633bdb0f90a57a2553d4..56ebc3062aed3090ccf26748b8d96a105bac85dc 100644 (file)
@@ -14,8 +14,6 @@
    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 "libpspp/message.h"
 #define _(msgid) gettext (msgid)
 #define N_(msgid) (msgid)
 
+#include "spreadsheet-reader.h"
 
 #if !GNM_SUPPORT
 
 struct casereader *
-gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
+gnumeric_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict)
 {
-  msg (ME, _("Support for Gnumeric files was not compiled into this installation of PSPP"));
+  msg (ME, _("Support for %s files was not compiled into this installation of PSPP"), "Gnumeric");
 
   return NULL;
 }
@@ -59,9 +58,6 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
 
 #include "gl/xalloc.h"
 
-/* Default width of string variables. */
-#define GNUMERIC_DEFAULT_WIDTH 8
-
 static void gnm_file_casereader_destroy (struct casereader *, void *);
 
 static struct ccase *gnm_file_casereader_read (struct casereader *, void *);
@@ -74,73 +70,6 @@ static const struct casereader_class gnm_file_casereader_class =
     NULL,
   };
 
-/* Convert a string, which is an integer encoded in base26
-   IE, A=0, B=1, ... Z=25 to the integer it represents.
-   ... except that in this scheme, digits with an exponent
-   greater than 1 are implicitly incremented by 1, so
-   AA  = 0 + 1*26, AB = 1 + 1*26,
-   ABC = 2 + 2*26 + 1*26^2 ....
-*/
-static int
-pseudo_base26 (const char *str)
-{
-  int i;
-  int multiplier = 1;
-  int result = 0;
-  int len = strlen (str);
-
-  for ( i = len - 1 ; i >= 0; --i)
-    {
-      int mantissa = (str[i] - 'A');
-
-      if ( mantissa < 0 || mantissa > 25 )
-       return -1;
-
-      if ( i != len - 1)
-       mantissa++;
-
-      result += mantissa * multiplier;
-
-      multiplier *= 26;
-    }
-
-  return result;
-}
-
-
-
-/* Convert a cell reference in the form "A1:B2", to
-   integers.  A1 means column zero, row zero.
-   B1 means column 1 row 0. AA1 means column 26, row 0.
-*/
-static bool
-convert_cell_ref (const char *ref,
-                 int *col0, int *row0,
-                 int *coli, int *rowi)
-{
-  char startcol[5];
-  char stopcol [5];
-
-  int startrow;
-  int stoprow;
-
-  int n = sscanf (ref, "%4[a-zA-Z]%d:%4[a-zA-Z]%d",
-             startcol, &startrow,
-             stopcol, &stoprow);
-  if ( n != 4)
-    return false;
-
-  str_uppercase (startcol);
-  *col0 = pseudo_base26 (startcol);
-  str_uppercase (stopcol);
-  *coli = pseudo_base26 (stopcol);
-  *row0 = startrow - 1;
-  *rowi = stoprow - 1 ;
-
-  return true;
-}
-
-
 enum reader_state
   {
     STATE_INIT = 0,        /* Initial state */
@@ -180,9 +109,6 @@ struct gnumeric_reader
 
 static void process_node (struct gnumeric_reader *r);
 
-#define _xml(X) (CHAR_CAST (const xmlChar *, X))
-
-#define _xmlchar_to_int(X) (atoi(CHAR_CAST (const char *, X)))
 
 static void
 gnm_file_casereader_destroy (struct casereader *reader UNUSED, void *r_)
@@ -345,7 +271,7 @@ struct var_spec
 };
 
 struct casereader *
-gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
+gnumeric_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict)
 {
   unsigned long int vstart = 0;
   int ret;
@@ -473,7 +399,7 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
 
              if (-1 ==  var_spec [idx].width )
                var_spec [idx].width = (gri->asw == -1) ?
-                 ROUND_UP (strlen(text), GNUMERIC_DEFAULT_WIDTH) : gri->asw;
+                 ROUND_UP (strlen(text), SPREADSHEET_DEFAULT_WIDTH) : gri->asw;
            }
 
          free (value);
@@ -506,7 +432,7 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
       /* Probably no data exists for this variable, so allocate a
         default width */
       if ( var_spec[i].width == -1 )
-       var_spec[i].width = GNUMERIC_DEFAULT_WIDTH;
+       var_spec[i].width = SPREADSHEET_DEFAULT_WIDTH;
 
       name = dict_make_unique_var_name (r->dict, var_spec[i].name, &vstart);
       dict_create_var (r->dict, name, var_spec[i].width);
index b313fc78768cf446975156c6d68647f277a72d4b..fcd338567543e3e17d0ad1c591cef59be23ad805 100644 (file)
 #include <stdbool.h>
 
 struct casereader;
-
-
-struct gnumeric_read_info
-{
-  char *sheet_name ;            /* In UTF-8. */
-  char *file_name ;             /* In filename encoding. */
-  char *cell_range ;            /* In UTF-8. */
-  int sheet_index ;
-  bool read_names ;
-  int asw ;
-};
-
 struct dictionary;
+struct spreadsheet_read_info;
 
-struct casereader * gnumeric_open_reader (struct gnumeric_read_info *, struct dictionary **);
+struct casereader * gnumeric_open_reader (struct spreadsheet_read_info *, struct dictionary **);
 
 
 #endif
diff --git a/src/data/ods-reader.c b/src/data/ods-reader.c
new file mode 100644 (file)
index 0000000..9bbfb47
--- /dev/null
@@ -0,0 +1,683 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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 "libpspp/message.h"
+#include "libpspp/misc.h"
+
+#include "data/data-in.h"
+
+#include "gl/minmax.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) (msgid)
+
+#include "ods-reader.h"
+#include "spreadsheet-reader.h"
+
+#if !ODF_READ_SUPPORT
+
+struct casereader *
+ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict)
+{
+  msg (ME, _("Support for %s files was not compiled into this installation of PSPP"), "OpenDocument");
+
+  return NULL;
+}
+
+#else
+
+#include "libpspp/zip-reader.h"
+
+
+#include <assert.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <libxml/xmlreader.h>
+#include <zlib.h>
+
+#include "data/format.h"
+#include "data/case.h"
+#include "data/casereader-provider.h"
+#include "data/dictionary.h"
+#include "data/identifier.h"
+#include "data/value.h"
+#include "data/variable.h"
+#include "libpspp/i18n.h"
+#include "libpspp/str.h"
+
+#include "gl/xalloc.h"
+
+static void ods_file_casereader_destroy (struct casereader *, void *);
+
+static struct ccase *ods_file_casereader_read (struct casereader *, void *);
+
+static const struct casereader_class ods_file_casereader_class =
+  {
+    ods_file_casereader_read,
+    ods_file_casereader_destroy,
+    NULL,
+    NULL,
+  };
+
+enum reader_state
+  {
+    STATE_INIT = 0,        /* Initial state */
+    STATE_SPREADSHEET,     /* Found the start of the spreadsheet doc */
+    STATE_TABLE,           /* Found the sheet that we actually want */
+    STATE_ROW,             /* Found the start of the cell array */
+    STATE_CELL,            /* Found a cell */
+    STATE_CELL_CONTENT     /* Found a the text within a cell */
+  };
+
+struct ods_reader
+{
+  xmlTextReaderPtr xtr;
+
+  enum reader_state state;
+  bool sheet_found;
+  int row;
+  int col;
+  int node_type;
+  int sheet_index;
+
+  const xmlChar *target_sheet;
+  int target_sheet_index;
+
+  int start_row;
+  int start_col;
+  int stop_row;
+  int stop_col;
+
+  struct caseproto *proto;
+  struct dictionary *dict;
+  struct ccase *first_case;
+  bool used_first_case;
+  bool read_names;
+
+  struct string ods_errs;
+  int span;
+};
+
+static void process_node (struct ods_reader *r);
+
+static void
+ods_file_casereader_destroy (struct casereader *reader UNUSED, void *r_)
+{
+  struct ods_reader *r = r_;
+  if ( r == NULL)
+    return ;
+
+  if (r->xtr)
+    xmlFreeTextReader (r->xtr);
+
+  if ( ! ds_is_empty (&r->ods_errs))
+    msg (ME, ds_cstr (&r->ods_errs));
+
+  ds_destroy (&r->ods_errs);
+
+  if ( ! r->used_first_case )
+    case_unref (r->first_case);
+
+  caseproto_unref (r->proto);
+
+  free (r);
+}
+
+static void
+process_node (struct ods_reader *r)
+{
+  xmlChar *name = xmlTextReaderName (r->xtr);
+  if (name == NULL)
+    name = xmlStrdup (_xml ("--"));
+
+  r->node_type = xmlTextReaderNodeType (r->xtr);
+
+  switch ( r->state)
+    {
+    case STATE_INIT:
+      if (0 == xmlStrcasecmp (name, _xml("office:spreadsheet")) &&
+         XML_READER_TYPE_ELEMENT  == r->node_type)
+       {
+         r->state = STATE_SPREADSHEET;
+       }
+      break;
+    case STATE_SPREADSHEET:
+      if (0 == xmlStrcasecmp (name, _xml("table:table")))
+       {
+         if (XML_READER_TYPE_ELEMENT == r->node_type)
+           {
+             r->col = -1;
+             r->row = -1;
+             ++r->sheet_index;
+             if ( r->target_sheet != NULL)
+               {
+                 xmlChar *value = xmlTextReaderGetAttribute (r->xtr, _xml ("table:name"));
+                 if ( 0 == xmlStrcmp (value, r->target_sheet))
+                   {
+                     r->sheet_found = true;
+                     r->state = STATE_TABLE;
+                   }
+                 free (value);
+               }
+             else if (r->target_sheet_index == r->sheet_index)
+               {
+                 r->sheet_found = true;
+                 r->state = STATE_TABLE;
+               }
+             else if ( r->target_sheet_index == -1)
+               r->state = STATE_TABLE;
+           }
+       }
+      else if (XML_READER_TYPE_END_ELEMENT  == r->node_type
+                  && r->sheet_found)
+       {
+         r->state = STATE_INIT;
+       }
+       break;
+    case STATE_TABLE:
+      if (0 == xmlStrcasecmp (name, _xml("table:table-row")) )
+       {
+         if ( XML_READER_TYPE_ELEMENT  == r->node_type)
+           {
+             if (! xmlTextReaderIsEmptyElement (r->xtr))
+               {
+                 r->state = STATE_ROW;
+               }
+             r->row++;
+             r->span = 1;
+           }
+       }
+      else if (XML_READER_TYPE_END_ELEMENT  == r->node_type)
+       {
+         r->state = STATE_SPREADSHEET;
+       }
+      break;
+    case STATE_ROW:
+      if (0 == xmlStrcasecmp (name, _xml ("table:table-cell")))
+       {
+         if ( XML_READER_TYPE_ELEMENT  == r->node_type)
+           {
+             xmlChar *value =
+               xmlTextReaderGetAttribute (r->xtr,
+                                          _xml ("table:number-columns-repeated"));
+             r->col += r->span;
+             r->span = value ? _xmlchar_to_int (value) : 1;
+             free (value);
+             if (! xmlTextReaderIsEmptyElement (r->xtr))
+               {
+                 r->state = STATE_CELL;
+               }
+           }
+       }
+      else if (XML_READER_TYPE_END_ELEMENT  == r->node_type)
+       {
+         r->state = STATE_TABLE;
+         r->col = -1;
+         /* Set the span back to the default */
+         r->span = 1;
+       }
+      break;
+    case STATE_CELL:
+      if (0 == xmlStrcasecmp (name, _xml("text:p")))
+       {
+         if ( XML_READER_TYPE_ELEMENT  == r->node_type)
+           {
+             r->state = STATE_CELL_CONTENT;
+           }
+       }
+      else if (XML_READER_TYPE_END_ELEMENT  == r->node_type)
+       {
+         r->state = STATE_ROW;
+       }
+      break;
+    case STATE_CELL_CONTENT:
+      if (XML_READER_TYPE_TEXT != r->node_type)
+       r->state = STATE_CELL;
+      break;
+    default:
+      break;
+    };
+
+  xmlFree (name);
+}
+
+/* 
+   A struct containing the parameters of a cell's value 
+   parsed from the xml
+*/
+struct xml_value
+{
+  xmlChar *type;
+  xmlChar *value;
+  xmlChar *text;
+};
+
+struct var_spec
+{
+  char *name;
+  struct xml_value firstval;
+};
+
+
+/* Determine the width that a xmv should probably have */
+static int
+xmv_to_width (const struct xml_value *xmv, int fallback)
+{
+  int width = SPREADSHEET_DEFAULT_WIDTH;
+
+  /* Non-strings always have zero width */
+  if (xmv->type != NULL && 0 != xmlStrcmp (xmv->type, _xml("string")))
+    return 0;
+
+  if ( fallback != -1)
+    return fallback;
+
+  if ( xmv->value )
+    width = ROUND_UP (xmlStrlen (xmv->value),
+                     SPREADSHEET_DEFAULT_WIDTH);
+  else if ( xmv->text)
+    width = ROUND_UP (xmlStrlen (xmv->text),
+                     SPREADSHEET_DEFAULT_WIDTH);
+
+  return width;
+}
+
+/*
+   Sets the VAR of case C, to the value corresponding to the xml data
+ */
+static void
+convert_xml_to_value (struct ccase *c, const struct variable *var,
+                     const struct xml_value *xmv)
+{
+  union value *v = case_data_rw (c, var);
+
+  if (xmv->value == NULL && xmv->text == NULL)
+    value_set_missing (v, var_get_width (var));
+  else if ( var_is_alpha (var))
+    /* Use the text field, because it seems that there is no
+       value field for strings */
+    value_copy_str_rpad (v, var_get_width (var), xmv->text, ' ');
+  else
+    {
+      const char *text ;
+      const struct fmt_spec *fmt = var_get_write_format (var);
+      enum fmt_category fc  = fmt_get_category (fmt->type);
+
+      assert ( fc != FMT_CAT_STRING);
+
+      text =
+        xmv->value ? CHAR_CAST (const char *, xmv->value) : CHAR_CAST (const char *, xmv->text);
+
+      data_in (ss_cstr (text), "UTF-8",
+              fmt->type,
+              v,
+              var_get_width (var),
+              "UTF-8");
+    }
+}
+
+
+struct casereader *
+ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict)
+{
+  int ret = 0;
+  xmlChar *type = NULL;
+  unsigned long int vstart = 0;
+  casenumber n_cases = CASENUMBER_MAX;
+  int i;
+  struct var_spec *var_spec = NULL;
+  int n_var_specs = 0;
+
+  struct ods_reader *r = xzalloc (sizeof *r);
+  struct zip_member *content = NULL;
+  struct zip_reader *zreader ;
+  xmlChar *val_string = NULL;
+
+  r->read_names = gri->read_names;
+  ds_init_empty (&r->ods_errs);
+
+  zreader = zip_reader_create (gri->file_name, &r->ods_errs);
+
+  if ( NULL == zreader)
+    {
+      msg (ME, _("Error opening `%s' for reading as a OpenDocument spreadsheet file: %s."),
+           gri->file_name, ds_cstr (&r->ods_errs));
+
+      goto error;
+    }
+
+  content = zip_member_open (zreader, "content.xml");
+  if ( NULL == content)
+    {
+      msg (ME, _("Could not extract OpenDocument spreadsheet from file `%s': %s."),
+           gri->file_name, ds_cstr (&r->ods_errs));
+
+      goto error;
+    }
+
+  zip_member_ref (content);
+
+  r->xtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read,
+                          (xmlInputCloseCallback) zip_member_finish,
+                          content,   NULL, NULL, XML_PARSE_RECOVER);
+
+  if ( r->xtr == NULL)
+    {
+      goto error;
+    }
+
+  if ( gri->cell_range )
+    {
+      if ( ! convert_cell_ref (gri->cell_range,
+                              &r->start_col, &r->start_row,
+                              &r->stop_col, &r->stop_row))
+       {
+         msg (SE, _("Invalid cell range `%s'"),
+              gri->cell_range);
+         goto error;
+       }
+    }
+  else
+    {
+      r->start_col = 0;
+      r->start_row = 0;
+      r->stop_col = -1;
+      r->stop_row = -1;
+    }
+
+  r->state = STATE_INIT;
+  r->target_sheet = BAD_CAST gri->sheet_name;
+  r->target_sheet_index = gri->sheet_index;
+  r->row = r->col = -1;
+  r->sheet_index = 0;
+
+
+  /* If CELLRANGE was given, then we know how many variables should be read */
+  if ( r->stop_col != -1 )
+    {
+      n_var_specs =  r->stop_col - r->start_col + 1;
+      var_spec = xrealloc (var_spec, sizeof (*var_spec) * n_var_specs);
+    }
+
+
+  /* Advance to the start of the cells for the target sheet */
+  while ( (r->row < r->start_row ))
+    {
+      if (1 != (ret = xmlTextReaderRead (r->xtr)))
+          break;
+
+      process_node (r);
+    }
+
+  if (ret < 1)
+    {
+      msg (MW, _("Selected sheet or range of spreadsheet `%s' is empty."),
+           gri->file_name);
+      goto error;
+    }
+
+  if ( gri->read_names)
+    {
+      while (1 == (ret = xmlTextReaderRead (r->xtr)))
+       {
+         int idx;
+         process_node (r);
+         if ( r->row > r->start_row)
+           break;
+
+         if (r->col == -1 && r->row == r->start_row)
+           break;
+
+         if ( r->col < r->start_col)
+           continue;
+
+         idx = r->col - r->start_col;
+
+         if (r->state == STATE_CELL_CONTENT 
+             &&
+             XML_READER_TYPE_TEXT  == r->node_type)
+           {
+             xmlChar *value = xmlTextReaderValue (r->xtr);
+             if ( idx >= n_var_specs)
+               {
+
+                 var_spec = xrealloc (var_spec, sizeof (*var_spec) * (idx + 1));
+
+                 /* xrealloc (unlike realloc) doesn't initialise its memory to 0 */
+                 memset (var_spec + n_var_specs * sizeof (*var_spec),
+                         0, 
+                         (n_var_specs - idx + 1) * sizeof (*var_spec));
+                 n_var_specs = idx + 1;
+               }
+             var_spec[idx].firstval.text = 0;
+             var_spec[idx].firstval.value = 0;
+             var_spec[idx].firstval.type = 0;
+
+             var_spec [idx].name = strdup (CHAR_CAST (const char *, value));
+             free (value);
+             value = NULL;
+           }
+       }
+    }
+
+  /* Read in the first row of data */
+  while (1 == xmlTextReaderRead (r->xtr))
+    {
+      int idx;
+      process_node (r);
+      if ( r->row >= r->start_row + 1 + gri->read_names)
+       break;
+
+      if ( r->col < r->start_col)
+       continue;
+
+      if ( r->col - r->start_col + 1 > n_var_specs)
+       continue;
+
+      idx = r->col - r->start_col;
+
+      if ( r->state == STATE_CELL &&
+          XML_READER_TYPE_ELEMENT  == r->node_type)
+       {
+         type = xmlTextReaderGetAttribute (r->xtr, _xml ("office:value-type"));
+         val_string = xmlTextReaderGetAttribute (r->xtr, _xml ("office:value"));
+       }
+
+      if ( r->state == STATE_CELL_CONTENT &&
+          XML_READER_TYPE_TEXT  == r->node_type)
+       {
+         var_spec [idx].firstval.type = type;
+         var_spec [idx].firstval.text = xmlTextReaderValue (r->xtr);
+         var_spec [idx].firstval.value = val_string;
+         val_string = NULL;
+         type = NULL;
+       }
+    }
+
+  /* Create the dictionary and populate it */
+  *dict = r->dict = dict_create (
+    CHAR_CAST (const char *, xmlTextReaderConstEncoding (r->xtr)));
+
+  for (i = 0 ; i < n_var_specs ; ++i )
+    {
+      struct fmt_spec fmt;
+      struct variable *var = NULL;
+      char *name = dict_make_unique_var_name (r->dict, var_spec[i].name, &vstart);
+      int width  = xmv_to_width (&var_spec[i].firstval, gri->asw);
+      dict_create_var (r->dict, name, width);
+      free (name);
+
+      var = dict_get_var (r->dict, i);
+
+      if ( 0 == xmlStrcmp (var_spec[i].firstval.type, _xml("date")))
+       {
+         fmt.type = FMT_DATE;
+         fmt.d = 0;
+         fmt.w = 20;
+       }
+      else
+       fmt = fmt_default_for_width (width);
+
+      var_set_both_formats (var, &fmt);
+    }
+
+  /* Create the first case, and cache it */
+  r->used_first_case = false;
+
+  if ( n_var_specs ==  0 )
+    {
+      msg (MW, _("Selected sheet or range of spreadsheet `%s' is empty."),
+           gri->file_name);
+      goto error;
+    }
+
+  r->proto = caseproto_ref (dict_get_proto (r->dict));
+  r->first_case = case_create (r->proto);
+  case_set_missing (r->first_case);
+
+  for ( i = 0 ; i < n_var_specs ; ++i )
+    {
+      const struct variable *var = dict_get_var (r->dict, i);
+
+      convert_xml_to_value (r->first_case, var,  &var_spec[i].firstval);
+    }
+
+  zip_reader_destroy (zreader);
+
+  for ( i = 0 ; i < n_var_specs ; ++i )
+    {
+      free (var_spec[i].firstval.type);
+      free (var_spec[i].firstval.value);
+      free (var_spec[i].firstval.text);
+      free (var_spec[i].name);
+    }
+
+  free (var_spec);
+
+  return casereader_create_sequential
+    (NULL,
+     r->proto,
+     n_cases,
+     &ods_file_casereader_class, r);
+
+ error:
+  
+  zip_reader_destroy (zreader);
+
+  for ( i = 0 ; i < n_var_specs ; ++i )
+    {
+      free (var_spec[i].firstval.type);
+      free (var_spec[i].firstval.value);
+      free (var_spec[i].firstval.text);
+      free (var_spec[i].name);
+    }
+
+  free (var_spec);
+
+  return NULL;
+}
+
+
+/* Reads and returns one case from READER's file.  Returns a null
+   pointer on failure. */
+static struct ccase *
+ods_file_casereader_read (struct casereader *reader UNUSED, void *r_)
+{
+  struct ccase *c = NULL;
+  xmlChar *val_string = NULL;
+  struct ods_reader *r = r_;
+  int current_row = r->row;
+
+  if ( r->row == -1)
+    return NULL;
+
+  if ( !r->used_first_case )
+    {
+      r->used_first_case = true;
+      return r->first_case;
+    }
+
+
+  if ( r->state > STATE_INIT)
+    {
+      c = case_create (r->proto);
+      case_set_missing (c);
+    }
+
+  while (1 == xmlTextReaderRead (r->xtr))
+    {
+      process_node (r);
+      if ( r->row > current_row)
+       {
+         break;
+       }
+      if ( r->col < r->start_col || (r->stop_col != -1 && r->col > r->stop_col))
+       {
+         continue;
+       }
+      if ( r->col - r->start_col >= caseproto_get_n_widths (r->proto))
+       {
+         continue;
+       }
+      if ( r->stop_row != -1 && r->row > r->stop_row)
+       {
+         continue;
+       }
+      if ( r->state == STATE_CELL &&
+          r->node_type == XML_READER_TYPE_ELEMENT )
+       {
+         val_string = xmlTextReaderGetAttribute (r->xtr, _xml ("office:value"));
+       }
+
+      if ( r->state == STATE_CELL_CONTENT && r->node_type == XML_READER_TYPE_TEXT )
+       {
+         int col;
+         struct xml_value *xmv = xzalloc (sizeof *xmv);
+         xmv->text = xmlTextReaderValue (r->xtr);
+         xmv->value = val_string;
+         val_string = NULL;
+
+         for (col = 0; col < r->span ; ++col)
+           {
+             const int idx = r->col + col - r->start_col;
+
+             const struct variable *var = dict_get_var (r->dict, idx);
+
+             convert_xml_to_value (c, var, xmv);
+           }
+         free (xmv->text);
+         free (xmv->value);
+         free (xmv);
+       }
+
+      if ( r->state < STATE_TABLE)
+       break;
+    }
+
+  if (NULL == c || (r->stop_row != -1 && r->row > r->stop_row + 1))
+    {
+      case_unref (c);
+      return NULL;
+    }
+  else
+    {
+      return c;
+    }
+}
+#endif
diff --git a/src/data/ods-reader.h b/src/data/ods-reader.h
new file mode 100644 (file)
index 0000000..79b7169
--- /dev/null
@@ -0,0 +1,27 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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/>. */
+
+#ifndef ODS_READ_H
+#define ODS_READ_H 1
+
+struct casereader;
+struct dictionary;
+struct spreadsheet_read_info;
+
+struct casereader * ods_open_reader (struct spreadsheet_read_info *, struct dictionary **);
+
+
+#endif
diff --git a/src/data/spreadsheet-reader.c b/src/data/spreadsheet-reader.c
new file mode 100644 (file)
index 0000000..11e8cf5
--- /dev/null
@@ -0,0 +1,89 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2007, 2009, 2010, 2011 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 "spreadsheet-reader.h"
+
+#include <libpspp/str.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Convert a string, which is an integer encoded in base26
+   IE, A=0, B=1, ... Z=25 to the integer it represents.
+   ... except that in this scheme, digits with an exponent
+   greater than 1 are implicitly incremented by 1, so
+   AA  = 0 + 1*26, AB = 1 + 1*26,
+   ABC = 2 + 2*26 + 1*26^2 ....
+*/
+int
+pseudo_base26 (const char *str)
+{
+  int i;
+  int multiplier = 1;
+  int result = 0;
+  int len = strlen (str);
+
+  for ( i = len - 1 ; i >= 0; --i)
+    {
+      int mantissa = (str[i] - 'A');
+
+      if ( mantissa < 0 || mantissa > 25 )
+       return -1;
+
+      if ( i != len - 1)
+       mantissa++;
+
+      result += mantissa * multiplier;
+
+      multiplier *= 26;
+    }
+
+  return result;
+}
+
+
+/* Convert a cell reference in the form "A1:B2", to
+   integers.  A1 means column zero, row zero.
+   B1 means column 1 row 0. AA1 means column 26, row 0.
+*/
+bool
+convert_cell_ref (const char *ref,
+                 int *col0, int *row0,
+                 int *coli, int *rowi)
+{
+  char startcol[5];
+  char stopcol [5];
+
+  int startrow;
+  int stoprow;
+
+  int n = sscanf (ref, "%4[a-zA-Z]%d:%4[a-zA-Z]%d",
+             startcol, &startrow,
+             stopcol, &stoprow);
+  if ( n != 4)
+    return false;
+
+  str_uppercase (startcol);
+  *col0 = pseudo_base26 (startcol);
+  str_uppercase (stopcol);
+  *coli = pseudo_base26 (stopcol);
+  *row0 = startrow - 1;
+  *rowi = stoprow - 1 ;
+
+  return true;
+}
+
diff --git a/src/data/spreadsheet-reader.h b/src/data/spreadsheet-reader.h
new file mode 100644 (file)
index 0000000..6edd705
--- /dev/null
@@ -0,0 +1,47 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2007, 2010 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/>. */
+
+#ifndef SPREADSHEET_READ_H
+#define SPREADSHEET_READ_H 1
+
+#include <stdbool.h>
+
+/* Default width of string variables. */
+#define SPREADSHEET_DEFAULT_WIDTH 8
+
+struct spreadsheet_read_info
+{
+  char *sheet_name ;            /* In UTF-8. */
+  char *file_name ;             /* In filename encoding. */
+  char *cell_range ;            /* In UTF-8. */
+  int sheet_index ;
+  bool read_names ;
+  int asw ;
+};
+
+int pseudo_base26 (const char *str);
+
+bool convert_cell_ref (const char *ref,
+                      int *col0, int *row0,
+                      int *coli, int *rowi);
+
+
+#define _xml(X) (CHAR_CAST (const xmlChar *, X))
+
+#define _xmlchar_to_int(X) (atoi(CHAR_CAST (const char *, X)))
+
+
+#endif
index 41f9221d436c66201393d7bf4efe2b705bce840d..1f9b62e1929114db84b74ad9ee8f517d88d9d085 100644 (file)
@@ -693,14 +693,12 @@ var_get_display_width (const struct variable *v)
 void
 var_set_display_width (struct variable *v, int new_width)
 {
-  int old_width = v->display_width;
-
-  v->display_width = new_width;
-
-  if ( old_width != new_width)
-    dict_var_display_width_changed (v);
-
-  dict_var_changed (v);
+  if (v->display_width != new_width)
+    {
+      v->display_width = new_width;
+      dict_var_display_width_changed (v);
+      dict_var_changed (v);
+    }
 }
 
 /* Returns the default display width for a variable of the given
index 016afcbbec1a0347fed92e42475372485b11bf96..f1acb02c9d13d4034488a57805c83d72021c0c0c 100644 (file)
@@ -119,6 +119,7 @@ DEF_CMD (S_DATA, 0, "FACTOR", cmd_factor)
 DEF_CMD (S_DATA, 0, "FILTER", cmd_filter)
 DEF_CMD (S_DATA, 0, "FLIP", cmd_flip)
 DEF_CMD (S_DATA, 0, "FREQUENCIES", cmd_frequencies)
+DEF_CMD (S_DATA, 0, "GLM", cmd_glm)
 DEF_CMD (S_DATA, 0, "LIST", cmd_list)
 DEF_CMD (S_DATA, 0, "MODIFY VARS", cmd_modify_vars)
 DEF_CMD (S_DATA, 0, "NPAR TESTS", cmd_npar_tests)
@@ -189,7 +190,6 @@ UNIMPL_CMD ("FIT", "Goodness of Fit")
 UNIMPL_CMD ("GENLOG", "Categorical model fitting")
 UNIMPL_CMD ("GET TRANSLATE", "Read other file formats")
 UNIMPL_CMD ("GGRAPH", "Custom defined graphs")
-UNIMPL_CMD ("GLM", "General Linear Model")
 UNIMPL_CMD ("GRAPH", "Draw graphs")
 UNIMPL_CMD ("HILOGLINEAR", "Hierarchial loglinear models")
 UNIMPL_CMD ("HOMALS", "Homogeneity analysis")
index 47b65b445adfc44ffa15e9b72c9738703fc687a0..9b878c553a92bf1a16e37f5985506e025db924c6 100644 (file)
 
 #include <stdlib.h>
 
+#include <string.h>
+
 #include "data/dataset.h"
 #include "data/dictionary.h"
 #include "data/format.h"
 #include "data/gnumeric-reader.h"
+#include "data/ods-reader.h"
+#include "data/spreadsheet-reader.h"
 #include "data/psql-reader.h"
 #include "data/settings.h"
 #include "language/command.h"
 #define _(msgid) gettext (msgid)
 #define N_(msgid) (msgid)
 
-static int parse_get_gnm (struct lexer *lexer, struct dataset *);
+static struct spreadsheet_read_info *parse_spreadsheet (struct lexer *lexer);
+static void destroy_spreadsheet_read_info (struct spreadsheet_read_info *);
+
 static int parse_get_txt (struct lexer *lexer, struct dataset *);
 static int parse_get_psql (struct lexer *lexer, struct dataset *);
 
 int
 cmd_get_data (struct lexer *lexer, struct dataset *ds)
 {
+  char *tok = NULL;
   lex_force_match (lexer, T_SLASH);
 
   if (!lex_force_match_id (lexer, "TYPE"))
@@ -54,14 +61,44 @@ cmd_get_data (struct lexer *lexer, struct dataset *ds)
 
   lex_force_match (lexer, T_EQUALS);
 
-  if (lex_match_id (lexer, "GNM"))
-    return parse_get_gnm (lexer, ds);
-  else if (lex_match_id (lexer, "TXT"))
-    return parse_get_txt (lexer, ds);
+  tok = strdup (lex_tokcstr (lexer));
+  if (lex_match_id (lexer, "TXT"))
+    {
+      return parse_get_txt (lexer, ds);
+    }
   else if (lex_match_id (lexer, "PSQL"))
-    return parse_get_psql (lexer, ds);
+    {
+      return parse_get_psql (lexer, ds);
+    }
+  else if (lex_match_id (lexer, "GNM") || 
+      lex_match_id (lexer, "ODS"))
+    {
+      struct casereader *reader = NULL;
+      struct dictionary *dict = NULL;
+      struct spreadsheet_read_info *sri = parse_spreadsheet (lexer);
+      if (NULL == sri)
+       goto error;
+
+      if ( 0 == strncasecmp (tok, "GNM", 3))
+       reader = gnumeric_open_reader (sri, &dict);
+      else if (0 == strncasecmp (tok, "ODS", 3))
+       reader = ods_open_reader (sri, &dict);
+
+      if (reader)
+       {
+         dataset_set_dict (ds, dict);
+         dataset_set_source (ds, reader);
+         destroy_spreadsheet_read_info (sri);
+         free (tok);
+         return CMD_SUCCESS;
+       }
+      destroy_spreadsheet_read_info (sri);
+    }
+  else
+    msg (SE, _("Unsupported TYPE %s."), tok);
 
-  msg (SE, _("Unsupported TYPE %s."), lex_tokcstr (lexer));
+ error:
+  free (tok);
   return CMD_FAILURE;
 }
 
@@ -141,10 +178,13 @@ parse_get_psql (struct lexer *lexer, struct dataset *ds)
   return CMD_FAILURE;
 }
 
-static int
-parse_get_gnm (struct lexer *lexer, struct dataset *ds)
+static struct spreadsheet_read_info *
+parse_spreadsheet (struct lexer *lexer)
 {
-  struct gnumeric_read_info gri  = {NULL, NULL, NULL, 1, true, -1};
+  struct spreadsheet_read_info *sri = xzalloc (sizeof *sri);
+  sri->sheet_index = 1;
+  sri->read_names = true;
+  sri->asw = -1;
 
   lex_force_match (lexer, T_SLASH);
 
@@ -156,7 +196,7 @@ parse_get_gnm (struct lexer *lexer, struct dataset *ds)
   if (!lex_force_string (lexer))
     goto error;
 
-  gri.file_name = utf8_to_filename (lex_tokcstr (lexer));
+  sri->file_name = utf8_to_filename (lex_tokcstr (lexer));
 
   lex_get (lexer);
 
@@ -165,7 +205,7 @@ parse_get_gnm (struct lexer *lexer, struct dataset *ds)
       if ( lex_match_id (lexer, "ASSUMEDSTRWIDTH"))
        {
          lex_match (lexer, T_EQUALS);
-         gri.asw = lex_integer (lexer);
+         sri->asw = lex_integer (lexer);
          lex_get (lexer);
        }
       else if (lex_match_id (lexer, "SHEET"))
@@ -176,14 +216,14 @@ parse_get_gnm (struct lexer *lexer, struct dataset *ds)
              if ( ! lex_force_string (lexer) )
                goto error;
 
-             gri.sheet_name = ss_xstrdup (lex_tokss (lexer));
-             gri.sheet_index = -1;
+             sri->sheet_name = ss_xstrdup (lex_tokss (lexer));
+             sri->sheet_index = -1;
 
              lex_get (lexer);
            }
          else if (lex_match_id (lexer, "INDEX"))
            {
-             gri.sheet_index = lex_integer (lexer);
+             sri->sheet_index = lex_integer (lexer);
              lex_get (lexer);
            }
          else
@@ -195,14 +235,14 @@ parse_get_gnm (struct lexer *lexer, struct dataset *ds)
 
          if (lex_match_id (lexer, "FULL"))
            {
-             gri.cell_range = NULL;
+             sri->cell_range = NULL;
            }
          else if (lex_match_id (lexer, "RANGE"))
            {
              if ( ! lex_force_string (lexer) )
                goto error;
 
-             gri.cell_range = ss_xstrdup (lex_tokss (lexer));
+             sri->cell_range = ss_xstrdup (lex_tokss (lexer));
              lex_get (lexer);
            }
          else
@@ -214,11 +254,11 @@ parse_get_gnm (struct lexer *lexer, struct dataset *ds)
 
          if ( lex_match_id (lexer, "ON"))
            {
-             gri.read_names = true;
+             sri->read_names = true;
            }
          else if (lex_match_id (lexer, "OFF"))
            {
-             gri.read_names = false;
+             sri->read_names = false;
            }
          else
            goto error;
@@ -230,30 +270,14 @@ parse_get_gnm (struct lexer *lexer, struct dataset *ds)
        }
     }
 
-  {
-    struct dictionary *dict = NULL;
-    struct casereader *reader = gnumeric_open_reader (&gri, &dict);
-
-    if ( reader )
-      {
-        dataset_set_dict (ds, dict);
-        dataset_set_source (ds, reader);
-      }
-  }
-
-  free (gri.file_name);
-  free (gri.sheet_name);
-  free (gri.cell_range);
-  return CMD_SUCCESS;
+  return sri;
 
  error:
-
-  free (gri.file_name);
-  free (gri.sheet_name);
-  free (gri.cell_range);
-  return CMD_FAILURE;
+  destroy_spreadsheet_read_info (sri);
+  return NULL;
 }
 
+
 static bool
 set_type (struct data_parser *parser, const char *subcommand,
           enum data_parser_type type, bool *has_type)
@@ -596,3 +620,16 @@ parse_get_txt (struct lexer *lexer, struct dataset *ds)
   free (name);
   return CMD_CASCADING_FAILURE;
 }
+
+
+static void 
+destroy_spreadsheet_read_info (struct spreadsheet_read_info *sri)
+{
+  if ( NULL == sri)
+    return;
+
+  free (sri->sheet_name);
+  free (sri->cell_range);
+  free (sri->file_name);
+  free (sri);
+}
index 1736ab80e8f8b942832bf490875b2568279fb87f..84236b8c9f76d17a72820b733bea6b6a11f34c52 100644 (file)
@@ -16,7 +16,7 @@
 
 #include <config.h>
 
-#include "language/expressions/evaluate.h"
+#include "evaluate.h"
 
 #include <ctype.h>
 
index 8f090778ab9c80a20fc6f44a24e7a7ba5b5d21aa..a926997d93bae1ac557fb4ec667d5b6a2694c0eb 100644 (file)
@@ -26,7 +26,7 @@
 #include "data/calendar.h"
 #include "data/data-in.h"
 #include "data/variable.h"
-#include "language/expressions/evaluate.h"
+#include "evaluate.h"
 #include "language/expressions/helpers.h"
 #include "language/expressions/public.h"
 #include "libpspp/assertion.h"
index 062d6f765185be6de3145397e4c30e7ae212394c..92adef85b3f401429964ba808c3fa3d3c24c1360 100644 (file)
@@ -21,8 +21,8 @@
 #include <stddef.h>
 
 #include "data/format.h"
-#include "language/expressions/operations.h"
-#include "language/expressions/public.h"
+#include "operations.h"
+#include "public.h"
 #include "libpspp/str.h"
 
 enum operation_flags
index 7b2022f02e068c67bc9feb839451fb9549bb4232..4b4510e96e3d58a7b6d66f793265ea23f9b82808 100644 (file)
@@ -7,8 +7,7 @@ src_language_stats_built_sources = \
        src/language/stats/examine.c \
        src/language/stats/frequencies.c \
        src/language/stats/rank.c \
-       src/language/stats/regression.c \
-       src/language/stats/t-test.c
+       src/language/stats/regression.c
 
 language_stats_sources = \
        src/language/stats/aggregate.c \
@@ -28,10 +27,15 @@ language_stats_sources = \
        src/language/stats/freq.h \
        src/language/stats/friedman.c \
        src/language/stats/friedman.h \
+       src/language/stats/glm.c \
        src/language/stats/kruskal-wallis.c \
        src/language/stats/kruskal-wallis.h \
+       src/language/stats/ks-one-sample.c \
+       src/language/stats/ks-one-sample.h \
        src/language/stats/mann-whitney.c \
        src/language/stats/mann-whitney.h \
+       src/language/stats/mcnemar.c \
+       src/language/stats/mcnemar.h \
        src/language/stats/npar.c  \
        src/language/stats/npar.h \
        src/language/stats/npar-summary.c \
@@ -48,6 +52,11 @@ language_stats_sources = \
        src/language/stats/sort-cases.c \
        src/language/stats/sort-criteria.c \
        src/language/stats/sort-criteria.h \
+       src/language/stats/t-test.h \
+       src/language/stats/t-test-indep.c \
+       src/language/stats/t-test-one-sample.c \
+       src/language/stats/t-test-paired.c \
+       src/language/stats/t-test-parser.c \
        src/language/stats/wilcoxon.c \
        src/language/stats/wilcoxon.h
 
index a4d34ccf608e7c784334d6a23546da546df1f095..33cab462c4d6ab226480722fe31cae218bdda6ff 100644 (file)
@@ -38,6 +38,7 @@
 
 #include "gl/xalloc.h"
 #include "gl/vasnprintf.h"
+#include "gl/mbiter.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
@@ -77,6 +78,9 @@ struct autorecode_pgm
 
   /* Hash table of "struct arc_item"s. */
   struct hmap *global_items;
+
+  bool blank_valid;
+  const struct dictionary *dict;
 };
 
 static trns_proc_func autorecode_trns_proc;
@@ -87,13 +91,35 @@ static void arc_free (struct autorecode_pgm *);
 static struct arc_item *find_arc_item (const struct arc_spec *, const union value *,
                                        size_t hash);
 
+static bool
+value_is_blank (const union value *val, int width, const struct dictionary *dict)
+{
+  mbi_iterator_t iter;
+  const char *str = CHAR_CAST_BUG (const char*, value_str (val, width));
+  char *text = recode_string (UTF8, dict_get_encoding (dict), str, width);
+
+  for (mbi_init (iter, text, width); mbi_avail (iter); mbi_advance (iter))
+    {
+      mbchar_t c = mbi_cur (iter);
+
+      if ( ! mb_isblank (c))
+       {
+         free (text);
+         return false;
+       }
+    }
+
+  free (text);
+  return true;
+}
+
 /* Performs the AUTORECODE procedure. */
 int
 cmd_autorecode (struct lexer *lexer, struct dataset *ds)
 {
   struct autorecode_pgm *arc = NULL;
-  struct dictionary *dict = dataset_dict (ds);
 
+  struct dictionary *dict = dataset_dict (ds);
   const struct variable **src_vars = NULL;
   char **dst_names = NULL;
   size_t n_srcs = 0;
@@ -110,17 +136,19 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
 
   /* Create procedure. */
   arc = xzalloc (sizeof *arc);
+  arc->blank_valid = true;
+  arc->dict = dataset_dict (ds);
 
   /* Parse variable lists. */
   lex_match_id (lexer, "VARIABLES");
   lex_match (lexer, T_EQUALS);
-  if (!parse_variables_const (lexer, dict, &src_vars, &n_srcs,
+  if (!parse_variables_const (lexer, arc->dict, &src_vars, &n_srcs,
                               PV_NO_DUPLICATE))
     goto error;
   if (!lex_force_match_id (lexer, "INTO"))
     goto error;
   lex_match (lexer, T_EQUALS);
-  if (!parse_DATA_LIST_vars (lexer, dict, &dst_names, &n_dsts,
+  if (!parse_DATA_LIST_vars (lexer, arc->dict, &dst_names, &n_dsts,
                              PV_NO_DUPLICATE))
     goto error;
   if (n_dsts != n_srcs)
@@ -135,7 +163,7 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
     {
       const char *name = dst_names[i];
 
-      if (dict_lookup_var (dict, name) != NULL)
+      if (dict_lookup_var (arc->dict, name) != NULL)
         {
           msg (SE, _("Target variable %s duplicates existing variable %s."),
                name, name);
@@ -155,6 +183,22 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
          arc->global_items = xmalloc (sizeof (*arc->global_items));
          hmap_init (arc->global_items);
        }
+      else if (lex_match_id (lexer, "BLANK"))
+       {
+         lex_match (lexer, T_EQUALS);
+         if (lex_match_id (lexer, "VALID"))
+           {
+             arc->blank_valid = true;
+           }
+         else if (lex_match_id (lexer, "MISSING"))
+           {
+             arc->blank_valid = false;
+           }
+         else
+           goto error;
+       }
+      else
+       goto error;
     }
 
   if (lex_token (lexer) != T_ENDCMD)
@@ -166,6 +210,7 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
   arc->specs = xmalloc (n_dsts * sizeof *arc->specs);
   arc->n_specs = n_dsts;
 
+
   for (i = 0; i < n_dsts; i++)
     {
       struct arc_spec *spec = &arc->specs[i];
@@ -195,7 +240,10 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
         struct arc_item *item;
 
         item = find_arc_item (spec, value, hash);
-        if (item == NULL)
+        if ( (item == NULL)
+            &&  
+            ( arc->blank_valid || var_is_numeric (spec->src) || ! value_is_blank (value, width, arc->dict))
+            )
           {
             item = xmalloc (sizeof *item);
            item->width = width;
@@ -251,7 +299,7 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
            {
              const char *str = CHAR_CAST_BUG (const char*, value_str (from, src_width));
 
-             recoded_value = recode_string (UTF8, dict_get_encoding (dict), str, src_width);
+             recoded_value = recode_string (UTF8, dict_get_encoding (arc->dict), str, src_width);
            }
          else
            recoded_value = asnprintf (NULL, &len, "%g", from->f);
@@ -374,9 +422,8 @@ autorecode_trns_proc (void *arc_, struct ccase **c,
       const struct arc_spec *spec = &arc->specs[i];
       int width = var_get_width (spec->src);
       const union value *value = case_data (*c, spec->src);
-      struct arc_item *item;
+      const struct arc_item *item = find_arc_item (spec, value, value_hash (value, width, 0));
 
-      item = find_arc_item (spec, value, value_hash (value, width, 0));
       case_data_rw (*c, spec->dst)->f = item ? item->to : SYSMIS;
     }
 
index 017b78c277a175ad4feeacedb0306db6b98d57e0..32a979d205fa413853c447c848f851f78b5f9752 100644 (file)
@@ -578,7 +578,7 @@ dump_z_table (struct dsc_proc *dsc)
     for (i = 0, y = 1; i < dsc->var_cnt; i++)
       if (dsc->vars[i].z_name != NULL)
        {
-         tab_text (t, 0, y, TAB_LEFT, var_get_name (dsc->vars[i].v));
+         tab_text (t, 0, y, TAB_LEFT, var_to_string (dsc->vars[i].v));
          tab_text (t, 1, y++, TAB_LEFT, dsc->vars[i].z_name);
        }
   }
@@ -914,7 +914,7 @@ display (struct dsc_proc *dsc)
       size_t j;
 
       nc = 0;
-      tab_text (t, nc++, i + 1, TAB_LEFT, var_get_name (dv->v));
+      tab_text (t, nc++, i + 1, TAB_LEFT, var_to_string (dv->v));
       tab_text_format (t, nc++, i + 1, 0, "%g", dv->valid);
       if (dsc->format == DSC_SERIAL)
        tab_text_format (t, nc++, i + 1, 0, "%g", dv->missing);
index a9c948e6369671ec6aa40f9a8103f91dbebb5ea4..e67cdbc1d8afaa6ea1ba07ea73f09efc7f9149ab 100644 (file)
@@ -22,6 +22,7 @@
 #include <gsl/gsl_eigen.h> 
 #include <gsl/gsl_blas.h> 
 #include <gsl/gsl_sort_vector.h>
+#include <gsl/gsl_cdf.h>
 
 #include "data/casegrouper.h"
 #include "data/casereader.h"
@@ -178,6 +179,8 @@ struct idata
   int n_extractions;
 
   gsl_vector *msr ;  /* Multiple Squared Regressions */
+
+  double detR;  /* The determinant of the correlation matrix */
 };
 
 static struct idata *
@@ -207,6 +210,54 @@ idata_free (struct idata *id)
 }
 
 
+static gsl_matrix *
+anti_image (const gsl_matrix *m)
+{
+  int i, j;
+  gsl_matrix *a;
+  assert (m->size1 == m->size2);
+
+  a = gsl_matrix_alloc (m->size1, m->size2);
+  
+  for (i = 0; i < m->size1; ++i)
+    {
+      for (j = 0; j < m->size2; ++j)
+       {
+         double *p = gsl_matrix_ptr (a, i, j);
+         *p = gsl_matrix_get (m, i, j);
+         *p /= gsl_matrix_get (m, i, i);
+         *p /= gsl_matrix_get (m, j, j);
+       }
+    }
+
+  return a;
+}
+
+
+/* Return the sum of all the elements excluding row N */
+static double
+ssq_od_n (const gsl_matrix *m, int n)
+{
+  int i, j;
+  double ss = 0;
+  assert (m->size1 == m->size2);
+
+  assert (n < m->size1);
+  
+  for (i = 0; i < m->size1; ++i)
+    {
+      if (i == n ) continue;
+      for (j = 0; j < m->size2; ++j)
+       {
+         ss += pow2 (gsl_matrix_get (m, i, j));
+       }
+    }
+
+  return ss;
+}
+
+
+
 #if 0
 static void
 dump_matrix (const gsl_matrix *m)
@@ -221,7 +272,6 @@ dump_matrix (const gsl_matrix *m)
     }
 }
 
-
 static void
 dump_matrix_permute (const gsl_matrix *m, const gsl_permutation *p)
 {
@@ -1049,10 +1099,11 @@ cmd_factor (struct lexer *lexer, struct dataset *ds)
                {
                  factor.print |= PRINT_INITIAL;
                }
-#if FACTOR_FULLY_IMPLEMENTED
              else if (lex_match_id (lexer, "KMO"))
                {
+                 factor.print |= PRINT_KMO;
                }
+#if FACTOR_FULLY_IMPLEMENTED
              else if (lex_match_id (lexer, "REPR"))
                {
                }
@@ -1647,22 +1698,9 @@ show_correlation_matrix (const struct cmd_factor *factor, const struct idata *id
 
   if (factor->print & PRINT_DETERMINANT)
     {
-      int sign = 0;
-      double det = 0.0;
-
-      const int size = idata->corr->size1;
-      gsl_permutation *p = gsl_permutation_calloc (size);
-      gsl_matrix *tmp = gsl_matrix_calloc (size, size);
-      gsl_matrix_memcpy (tmp, idata->corr);
-
-      gsl_linalg_LU_decomp (tmp, p, &sign);
-      det = gsl_linalg_LU_det (tmp, sign);
-      gsl_permutation_free (p);
-      gsl_matrix_free (tmp);
-
-
       tab_text (t, 0, nr, TAB_LEFT | TAT_TITLE, _("Determinant"));
-      tab_double (t, 1, nr, 0, det, NULL);
+
+      tab_double (t, 1, nr, 0, idata->detR, NULL);
     }
 
   tab_submit (t);
@@ -1703,17 +1741,33 @@ do_factor (const struct cmd_factor *factor, struct casereader *r)
   if ( factor->method == METHOD_CORR)
     {
       idata->corr = correlation_from_covariance (idata->cov, var_matrix);
+      
       analysis_matrix = idata->corr;
     }
   else
     analysis_matrix = idata->cov;
 
+  if (factor->print & PRINT_DETERMINANT
+      || factor->print & PRINT_KMO)
+    {
+      int sign = 0;
+
+      const int size = idata->corr->size1;
+      gsl_permutation *p = gsl_permutation_calloc (size);
+      gsl_matrix *tmp = gsl_matrix_calloc (size, size);
+      gsl_matrix_memcpy (tmp, idata->corr);
+
+      gsl_linalg_LU_decomp (tmp, p, &sign);
+      idata->detR = gsl_linalg_LU_det (tmp, sign);
+      gsl_permutation_free (p);
+      gsl_matrix_free (tmp);
+    }
+
   if ( factor->print & PRINT_UNIVARIATE)
     {
+      const struct fmt_spec *wfmt = factor->wv ? var_get_print_format (factor->wv) : & F_8_0;
       const int nc = 4;
       int i;
-      const struct fmt_spec *wfmt = factor->wv ? var_get_print_format (factor->wv) : & F_8_0;
-
 
       const int heading_columns = 1;
       const int heading_rows = 1;
@@ -1759,9 +1813,88 @@ do_factor (const struct cmd_factor *factor, struct casereader *r)
       tab_submit (t);
     }
 
+  if (factor->print & PRINT_KMO)
+    {
+      int i;
+      double sum_ssq_r = 0;
+      double sum_ssq_a = 0;
+
+      double df = factor->n_vars * ( factor->n_vars - 1) / 2;
+
+      double w = 0;
+
+
+      double xsq;
+
+      const int heading_columns = 2;
+      const int heading_rows = 0;
+
+      const int nr = heading_rows + 4;
+      const int nc = heading_columns + 1;
+
+      gsl_matrix *a, *x;
+
+      struct tab_table *t = tab_create (nc, nr);
+      tab_title (t, _("KMO and Bartlett's Test"));
+
+      x  = clone_matrix (idata->corr);
+      gsl_linalg_cholesky_decomp (x);
+      gsl_linalg_cholesky_invert (x);
+
+      a = anti_image (x);
+
+      for (i = 0; i < x->size1; ++i)
+       {
+         sum_ssq_r += ssq_od_n (x, i);
+         sum_ssq_a += ssq_od_n (a, i);
+       }
+
+      gsl_matrix_free (a);
+      gsl_matrix_free (x);
+
+      tab_headers (t, heading_columns, 0, heading_rows, 0);
+
+      /* Outline the box */
+      tab_box (t,
+              TAL_2, TAL_2,
+              -1, -1,
+              0, 0,
+              nc - 1, nr - 1);
+
+      tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
+
+      tab_text (t, 0, 0, TAT_TITLE | TAB_LEFT, _("Kaiser-Meyer-Olkin Measure of Sampling Adequacy"));
+
+      tab_double (t, 2, 0, 0, sum_ssq_r /  (sum_ssq_r + sum_ssq_a), NULL);
+
+      tab_text (t, 0, 1, TAT_TITLE | TAB_LEFT, _("Bartlett's Test of Sphericity"));
+
+      tab_text (t, 1, 1, TAT_TITLE, _("Approx. Chi-Square"));
+      tab_text (t, 1, 2, TAT_TITLE, _("df"));
+      tab_text (t, 1, 3, TAT_TITLE, _("Sig."));
+
+
+      /* The literature doesn't say what to do for the value of W when 
+        missing values are involved.  The best thing I can think of
+        is to take the mean average. */
+      w = 0;
+      for (i = 0; i < idata->n->size1; ++i)
+       w += gsl_matrix_get (idata->n, i, i);
+      w /= idata->n->size1;
+
+      xsq = w - 1 - (2 * factor->n_vars + 5) / 6.0;
+      xsq *= -log (idata->detR);
+
+      tab_double (t, 2, 1, 0, xsq, NULL);
+      tab_double (t, 2, 2, 0, df, &F_8_0);
+      tab_double (t, 2, 3, 0, gsl_cdf_chisq_Q (xsq, df), NULL);
+      
+
+      tab_submit (t);
+    }
+
   show_correlation_matrix (factor, idata);
 
-#if 1
   {
     gsl_eigen_symmv_workspace *workspace = gsl_eigen_symmv_alloc (factor->n_vars);
     
@@ -1771,7 +1904,6 @@ do_factor (const struct cmd_factor *factor, struct casereader *r)
   }
 
   gsl_eigen_symmv_sort (idata->eval, idata->evec, GSL_EIGEN_SORT_ABS_DESC);
-#endif
 
   idata->n_extractions = n_extracted_factors (factor, idata);
 
index 6049f1fa9c9acfbde0cd035c808e849ccd067c65..283a2266a4568a5c57a8fe2354620cf51d51bf31 100644 (file)
@@ -14,7 +14,7 @@
    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 <config.h>
 
 #include <ctype.h>
 #include <errno.h>
index b8aa71cb4dae06e0ef2520e96a69799ab338d556..f8a7f133cc254d19493c8856f16a656bee4ad935 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <gsl/gsl_cdf.h>
 #include <gsl/gsl_matrix.h>
+#include <gsl/gsl_combination.h>
 #include <math.h>
 
 #include "data/case.h"
@@ -39,6 +40,7 @@
 #include "linreg/sweep.h"
 #include "math/categoricals.h"
 #include "math/covariance.h"
+#include "math/interaction.h"
 #include "math/moments.h"
 #include "output/tab.h"
 
@@ -53,74 +55,128 @@ struct glm_spec
   size_t n_factor_vars;
   const struct variable **factor_vars;
 
+  size_t n_interactions;
+  struct interaction **interactions;
+
   enum mv_class exclude;
 
   /* The weight variable */
   const struct variable *wv;
 
-  /* 
-     Sums of squares due to different variables. Element 0 is the SSE
-     for the entire model. For i > 0, element i is the SS due to
-     variable i.
-   */
-  gsl_vector * ssq;
+  const struct dictionary *dict;
 
   bool intercept;
+
+  double alpha;
 };
 
 struct glm_workspace
 {
   double total_ssq;
   struct moments *totals;
+
+  struct categoricals *cats;
+
+  /* 
+     Sums of squares due to different variables. Element 0 is the SSE
+     for the entire model. For i > 0, element i is the SS due to
+     variable i.
+   */
+  gsl_vector *ssq;
 };
 
-static void output_glm (struct glm_spec *, const struct glm_workspace *ws);
-static void run_glm (struct glm_spec *cmd, struct casereader *input, const struct dataset *ds);
+
+/* Default design: all possible interactions */
+static void
+design_full (struct glm_spec *glm)
+{
+  int sz;
+  int i = 0;
+  glm->n_interactions = (1 << glm->n_factor_vars) - 1;
+
+  glm->interactions = xcalloc (glm->n_interactions, sizeof *glm->interactions);
+
+  /* All subsets, with exception of the empty set, of [0, glm->n_factor_vars) */
+  for (sz = 1; sz <= glm->n_factor_vars; ++sz)
+    {
+      gsl_combination *c = gsl_combination_calloc (glm->n_factor_vars, sz);
+
+      do
+       {
+         struct interaction *iact = interaction_create (NULL);
+         int e;
+         for (e = 0 ; e < gsl_combination_k (c); ++e)
+           interaction_add_variable (iact, glm->factor_vars [gsl_combination_get (c, e)]);
+
+         glm->interactions[i++] = iact;
+       }
+      while (gsl_combination_next (c) == GSL_SUCCESS);
+
+      gsl_combination_free (c);
+    }
+}
+
+static void output_glm (const struct glm_spec *,
+                       const struct glm_workspace *ws);
+static void run_glm (struct glm_spec *cmd, struct casereader *input,
+                    const struct dataset *ds);
+
+
+static bool parse_design_spec (struct lexer *lexer, struct glm_spec *glm);
+
+/* Define to 1 if the /DESIGN subcommand should not be optional */
+#define DESIGN_MANDATORY 1
 
 int
 cmd_glm (struct lexer *lexer, struct dataset *ds)
 {
-  const struct dictionary *dict = dataset_dict (ds);  
-  struct glm_spec glm ;
+  int i;
+  struct const_var_set *factors = NULL;
+  struct glm_spec glm;
+  bool design = false;
+  glm.dict = dataset_dict (ds);
   glm.n_dep_vars = 0;
   glm.n_factor_vars = 0;
+  glm.n_interactions = 0;
+  glm.interactions = NULL;
   glm.dep_vars = NULL;
   glm.factor_vars = NULL;
   glm.exclude = MV_ANY;
   glm.intercept = true;
-  glm.wv = dict_get_weight (dict);
+  glm.wv = dict_get_weight (glm.dict);
+  glm.alpha = 0.05;
 
-  
-  if (!parse_variables_const (lexer, dict,
+  if (!parse_variables_const (lexer, glm.dict,
                              &glm.dep_vars, &glm.n_dep_vars,
                              PV_NO_DUPLICATE | PV_NUMERIC))
     goto error;
 
   lex_force_match (lexer, T_BY);
 
-  if (!parse_variables_const (lexer, dict,
+  if (!parse_variables_const (lexer, glm.dict,
                              &glm.factor_vars, &glm.n_factor_vars,
                              PV_NO_DUPLICATE | PV_NUMERIC))
     goto error;
 
-  if ( glm.n_dep_vars > 1)
+  if (glm.n_dep_vars > 1)
     {
       msg (ME, _("Multivariate analysis is not yet implemented"));
       return CMD_FAILURE;
     }
 
-  struct const_var_set *factors = const_var_set_create_from_array (glm.factor_vars, glm.n_factor_vars);
-
+  factors =
+    const_var_set_create_from_array (glm.factor_vars, glm.n_factor_vars);
 
   while (lex_token (lexer) != T_ENDCMD)
     {
       lex_match (lexer, T_SLASH);
 
       if (lex_match_id (lexer, "MISSING"))
-        {
-          lex_match (lexer, T_EQUALS);
-          while (lex_token (lexer) != T_ENDCMD && lex_token (lexer) != T_SLASH)
-            {
+       {
+         lex_match (lexer, T_EQUALS);
+         while (lex_token (lexer) != T_ENDCMD
+                && lex_token (lexer) != T_SLASH)
+           {
              if (lex_match_id (lexer, "INCLUDE"))
                {
                  glm.exclude = MV_SYSTEM;
@@ -131,16 +187,17 @@ cmd_glm (struct lexer *lexer, struct dataset *ds)
                }
              else
                {
-                  lex_error (lexer, NULL);
+                 lex_error (lexer, NULL);
                  goto error;
                }
            }
        }
       else if (lex_match_id (lexer, "INTERCEPT"))
-        {
-          lex_match (lexer, T_EQUALS);
-          while (lex_token (lexer) != T_ENDCMD && lex_token (lexer) != T_SLASH)
-            {
+       {
+         lex_match (lexer, T_EQUALS);
+         while (lex_token (lexer) != T_ENDCMD
+                && lex_token (lexer) != T_SLASH)
+           {
              if (lex_match_id (lexer, "INCLUDE"))
                {
                  glm.intercept = true;
@@ -151,18 +208,93 @@ cmd_glm (struct lexer *lexer, struct dataset *ds)
                }
              else
                {
-                  lex_error (lexer, NULL);
+                 lex_error (lexer, NULL);
                  goto error;
                }
            }
        }
+      else if (lex_match_id (lexer, "CRITERIA"))
+       {
+         lex_match (lexer, T_EQUALS);
+         if (lex_match_id (lexer, "ALPHA"))
+           {
+             if (lex_force_match (lexer, T_LPAREN))
+               {
+                 if (! lex_force_num (lexer))
+                   {
+                     lex_error (lexer, NULL);
+                     goto error;
+                   }
+                 
+                 glm.alpha = lex_number (lexer);
+                 lex_get (lexer);
+                 if ( ! lex_force_match (lexer, T_RPAREN))
+                   {
+                     lex_error (lexer, NULL);
+                     goto error;
+                   }
+               }
+           }
+         else
+           {
+             lex_error (lexer, NULL);
+             goto error;
+           }
+       }
+      else if (lex_match_id (lexer, "METHOD"))
+       {
+         lex_match (lexer, T_EQUALS);
+         if ( !lex_force_match_id (lexer, "SSTYPE"))
+           {
+             lex_error (lexer, NULL);
+             goto error;
+           }
+
+         if ( ! lex_force_match (lexer, T_LPAREN))
+           {
+             lex_error (lexer, NULL);
+             goto error;
+           }
+
+         if ( ! lex_force_int (lexer))
+           {
+             lex_error (lexer, NULL);
+             goto error;
+           }
+
+         if (3 != lex_integer (lexer))
+           {
+             msg (ME, _("Only type 3 sum of squares are currently implemented"));
+             goto error;
+           }
+
+         lex_get (lexer);
+
+         if ( ! lex_force_match (lexer, T_RPAREN))
+           {
+             lex_error (lexer, NULL);
+             goto error;
+           }
+       }
       else if (lex_match_id (lexer, "DESIGN"))
-        {
-         size_t n_des;
-         const struct variable **des;
-          lex_match (lexer, T_EQUALS);
+       {
+         lex_match (lexer, T_EQUALS);
+
+         if (! parse_design_spec (lexer, &glm))
+           goto error;
 
-         parse_const_var_set_vars (lexer, factors, &des, &n_des, 0);
+#if DESIGN_MANDATORY
+         if ( glm.n_interactions == 0)
+           {
+             msg (ME, _("One or more design  variables must be given"));
+             goto error;
+           }
+         
+         design = true;
+#else
+         if (glm.n_interactions > 0)
+           design = true;
+#endif
        }
       else
        {
@@ -171,72 +303,95 @@ cmd_glm (struct lexer *lexer, struct dataset *ds)
        }
     }
 
+  if ( ! design )
+    {
+#if DESIGN_MANDATORY
+      lex_error (lexer, _("/DESIGN is mandatory in GLM"));
+      goto error;
+#endif
+
+      design_full (&glm);
+    }
 
   {
     struct casegrouper *grouper;
     struct casereader *group;
     bool ok;
 
-    grouper = casegrouper_create_splits (proc_open (ds), dict);
+    grouper = casegrouper_create_splits (proc_open (ds), glm.dict);
     while (casegrouper_get_next_group (grouper, &group))
       run_glm (&glm, group, ds);
     ok = casegrouper_destroy (grouper);
     ok = proc_commit (ds) && ok;
   }
 
+  const_var_set_destroy (factors);
+  free (glm.factor_vars);
+  for (i = 0 ; i < glm.n_interactions; ++i)
+    interaction_destroy (glm.interactions[i]);
+  free (glm.interactions);
+  free (glm.dep_vars);
+
+
   return CMD_SUCCESS;
 
- error:
+error:
+
+  const_var_set_destroy (factors);
+  free (glm.factor_vars);
+  for (i = 0 ; i < glm.n_interactions; ++i)
+    interaction_destroy (glm.interactions[i]);
+
+  free (glm.interactions);
+  free (glm.dep_vars);
+
   return CMD_FAILURE;
 }
 
-static void get_ssq (struct covariance *, gsl_vector *, struct glm_spec *);
+static void get_ssq (struct covariance *, gsl_vector *,
+                    const struct glm_spec *);
 
 static bool
-not_dropped (size_t j, size_t * dropped, size_t n_dropped)
+not_dropped (size_t j, const size_t *dropped, size_t n_dropped)
 {
   size_t i;
 
   for (i = 0; i < n_dropped; i++)
     {
-      if (j == dropped [i])
+      if (j == dropped[i])
        return false;
     }
   return true;
 }
 
 static void
-get_ssq (struct covariance * cov, gsl_vector * ssq, struct glm_spec * cmd)
+get_ssq (struct covariance *cov, gsl_vector *ssq, const struct glm_spec *cmd)
 {
-  const struct variable **vars;
-  gsl_matrix * small_cov = NULL;
-  gsl_matrix * cm = covariance_calculate_unnormalized (cov);
+  gsl_matrix *cm = covariance_calculate_unnormalized (cov);
   size_t i;
   size_t j;
   size_t k;
-  size_t n;
-  size_t m;
-  size_t * dropped;
-  size_t n_dropped;
+  size_t *dropped = xcalloc (covariance_dim (cov), sizeof (*dropped));
+  const struct categoricals *cats = covariance_get_categoricals (cov);
 
-  dropped = xcalloc (covariance_dim (cov), sizeof (*dropped));
-  vars = xcalloc (covariance_dim (cov), sizeof (*vars));
-  covariance_get_var_indices (cov, vars);
-
-  for (k = 0; k < cmd->n_factor_vars; k++)
+  for (k = 0; k < cmd->n_interactions; k++)
     {
-      n_dropped = 0;
-      for (i = 1; i < covariance_dim (cov); i++)
+      size_t n = 0;
+      size_t m = 0;
+      gsl_matrix *small_cov = NULL;
+      size_t n_dropped = 0;
+      for (i = cmd->n_dep_vars; i < covariance_dim (cov); i++)
        {
-         if (vars [i] == cmd->factor_vars [k])
+         if (categoricals_get_interaction_by_subscript (cats, i - cmd->n_dep_vars)
+             == cmd->interactions[k])
            {
-             dropped [n_dropped++] = i;
+             assert (n_dropped < covariance_dim (cov));
+             dropped[n_dropped++] = i;
            }
        }
-      small_cov = gsl_matrix_alloc (cm->size1 - n_dropped, cm->size2 - n_dropped);
+      small_cov =
+       gsl_matrix_alloc (cm->size1 - n_dropped, cm->size2 - n_dropped);
       gsl_matrix_set (small_cov, 0, 0, gsl_matrix_get (cm, 0, 0));
-      n = 0;
-      m = 0;
       for (i = 0; i < cm->size1; i++)
        {
          if (not_dropped (i, dropped, n_dropped))
@@ -246,7 +401,8 @@ get_ssq (struct covariance * cov, gsl_vector * ssq, struct glm_spec * cmd)
                {
                  if (not_dropped (j, dropped, n_dropped))
                    {
-                     gsl_matrix_set (small_cov, n, m, gsl_matrix_get (cm, i, j));
+                     gsl_matrix_set (small_cov, n, m,
+                                     gsl_matrix_get (cm, i, j));
                      m++;
                    }
                }
@@ -254,23 +410,23 @@ get_ssq (struct covariance * cov, gsl_vector * ssq, struct glm_spec * cmd)
            }
        }
       reg_sweep (small_cov, 0);
-      gsl_vector_set (ssq, k + 1, 
+      gsl_vector_set (ssq, k + 1,
                      gsl_matrix_get (small_cov, 0, 0)
                      - gsl_vector_get (ssq, 0));
       gsl_matrix_free (small_cov);
     }
 
   free (dropped);
-  free (vars);
   gsl_matrix_free (cm);
-
 }
 
-static  void dump_matrix (const gsl_matrix *m);
+//static  void dump_matrix (const gsl_matrix *m);
 
 static void
-run_glm (struct glm_spec *cmd, struct casereader *input, const struct dataset *ds)
+run_glm (struct glm_spec *cmd, struct casereader *input,
+        const struct dataset *ds)
 {
+  bool warn_bad_weight = true;
   int v;
   struct taint *taint;
   struct dictionary *dict = dataset_dict (ds);
@@ -278,15 +434,14 @@ run_glm (struct glm_spec *cmd, struct casereader *input, const struct dataset *d
   struct ccase *c;
 
   struct glm_workspace ws;
+  struct covariance *cov;
 
-  struct categoricals *cats = categoricals_create (cmd->factor_vars, cmd->n_factor_vars,
-                                                  cmd->wv, cmd->exclude, 
-                                                  NULL, NULL,
-                                                  NULL, NULL);
-  
-  struct covariance *cov = covariance_2pass_create (cmd->n_dep_vars, cmd->dep_vars,
-                                              cats, 
-                                              cmd->wv, cmd->exclude);
+  ws.cats = categoricals_create (cmd->interactions, cmd->n_interactions,
+                                cmd->wv, cmd->exclude,
+                                NULL, NULL, NULL, NULL);
+
+  cov = covariance_2pass_create (cmd->n_dep_vars, cmd->dep_vars,
+                                ws.cats, cmd->wv, cmd->exclude);
 
 
   c = casereader_peek (input, 0);
@@ -302,28 +457,27 @@ run_glm (struct glm_spec *cmd, struct casereader *input, const struct dataset *d
 
   ws.totals = moments_create (MOMENT_VARIANCE);
 
-  bool warn_bad_weight = true;
   for (reader = casereader_clone (input);
        (c = casereader_read (reader)) != NULL; case_unref (c))
     {
       double weight = dict_get_case_weight (dict, c, &warn_bad_weight);
 
-      for ( v = 0; v < cmd->n_dep_vars; ++v)
-       moments_pass_one (ws.totals, case_data (c, cmd->dep_vars[v])->f, weight);
+      for (v = 0; v < cmd->n_dep_vars; ++v)
+       moments_pass_one (ws.totals, case_data (c, cmd->dep_vars[v])->f,
+                         weight);
 
       covariance_accumulate_pass1 (cov, c);
     }
   casereader_destroy (reader);
 
-  categoricals_done (cats);
-
-  for (reader = casereader_clone (input);
+  for (reader = input;
        (c = casereader_read (reader)) != NULL; case_unref (c))
     {
       double weight = dict_get_case_weight (dict, c, &warn_bad_weight);
 
-      for ( v = 0; v < cmd->n_dep_vars; ++v)
-       moments_pass_two (ws.totals, case_data (c, cmd->dep_vars[v])->f, weight);
+      for (v = 0; v < cmd->n_dep_vars; ++v)
+       moments_pass_two (ws.totals, case_data (c, cmd->dep_vars[v])->f,
+                         weight);
 
       covariance_accumulate_pass2 (cov, c);
     }
@@ -332,7 +486,7 @@ run_glm (struct glm_spec *cmd, struct casereader *input, const struct dataset *d
   {
     gsl_matrix *cm = covariance_calculate_unnormalized (cov);
 
-    dump_matrix (cm);
+    //    dump_matrix (cm);
 
     ws.total_ssq = gsl_matrix_get (cm, 0, 0);
 
@@ -340,13 +494,11 @@ run_glm (struct glm_spec *cmd, struct casereader *input, const struct dataset *d
 
     /*
       Store the overall SSE.
-     */
-    cmd->ssq = gsl_vector_alloc (cm->size1);
-    gsl_vector_set (cmd->ssq, 0, gsl_matrix_get (cm, 0, 0));
-    get_ssq (cov, cmd->ssq, cmd);
-
-    gsl_vector_free (cmd->ssq);
-    dump_matrix (cm);
+    */
+    ws.ssq = gsl_vector_alloc (cm->size1);
+    gsl_vector_set (ws.ssq, 0, gsl_matrix_get (cm, 0, 0));
+    get_ssq (cov, ws.ssq, cmd);
+    //    dump_matrix (cm);
 
     gsl_matrix_free (cm);
   }
@@ -354,22 +506,32 @@ run_glm (struct glm_spec *cmd, struct casereader *input, const struct dataset *d
   if (!taint_has_tainted_successor (taint))
     output_glm (cmd, &ws);
 
+  gsl_vector_free (ws.ssq);
+
+  covariance_destroy (cov);
+  moments_destroy (ws.totals);
+
   taint_destroy (taint);
 }
 
 static void
-output_glm (struct glm_spec *cmd, const struct glm_workspace *ws)
+output_glm (const struct glm_spec *cmd, const struct glm_workspace *ws)
 {
-  const struct fmt_spec *wfmt = cmd->wv ? var_get_print_format (cmd->wv) : &F_8_0;
+  const struct fmt_spec *wfmt =
+    cmd->wv ? var_get_print_format (cmd->wv) : &F_8_0;
+
+  double n_total, mean;
+  double df_corr = 0.0;
+  double mse = 0;
 
   int f;
   int r;
   const int heading_columns = 1;
   const int heading_rows = 1;
-  struct tab_table *t ;
+  struct tab_table *t;
 
   const int nc = 6;
-  int nr = heading_rows + 4 + cmd->n_factor_vars;
+  int nr = heading_rows + 4 + cmd->n_interactions;
   if (cmd->intercept)
     nr++;
 
@@ -378,11 +540,7 @@ output_glm (struct glm_spec *cmd, const struct glm_workspace *ws)
 
   tab_headers (t, heading_columns, 0, heading_rows, 0);
 
-  tab_box (t,
-          TAL_2, TAL_2,
-          -1, TAL_1,
-          0, 0,
-          nc - 1, nr - 1);
+  tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, nc - 1, nr - 1);
 
   tab_hline (t, TAL_2, 0, nc - 1, heading_rows);
   tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
@@ -390,42 +548,91 @@ output_glm (struct glm_spec *cmd, const struct glm_workspace *ws)
   tab_text (t, 0, 0, TAB_CENTER | TAT_TITLE, _("Source"));
 
   /* TRANSLATORS: The parameter is a roman numeral */
-  tab_text_format (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Type %s Sum of Squares"), "III");
+  tab_text_format (t, 1, 0, TAB_CENTER | TAT_TITLE,
+                  _("Type %s Sum of Squares"), "III");
   tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("df"));
   tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Mean Square"));
   tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("F"));
   tab_text (t, 5, 0, TAB_CENTER | TAT_TITLE, _("Sig."));
 
+  moments_calculate (ws->totals, &n_total, &mean, NULL, NULL, NULL);
+
+  if (cmd->intercept)
+    df_corr += 1.0;
+
+  df_corr += categoricals_df_total (ws->cats);
+
+  mse = gsl_vector_get (ws->ssq, 0) / (n_total - df_corr);
+
   r = heading_rows;
-  tab_text (t, 0, r++, TAB_LEFT | TAT_TITLE, _("Corrected Model"));
+  tab_text (t, 0, r, TAB_LEFT | TAT_TITLE, _("Corrected Model"));
+
+  r++;
 
-  double intercept, n_total;
   if (cmd->intercept)
     {
-      double mean;
-      moments_calculate (ws->totals, &n_total, &mean, NULL, NULL, NULL);
-      intercept = pow2 (mean * n_total) / n_total;
-
+      const double intercept = pow2 (mean * n_total) / n_total;
+      const double df = 1.0;
+      const double F = intercept / df / mse;
       tab_text (t, 0, r, TAB_LEFT | TAT_TITLE, _("Intercept"));
       tab_double (t, 1, r, 0, intercept, NULL);
       tab_double (t, 2, r, 0, 1.00, wfmt);
-
-      tab_double (t, 3, r, 0, intercept / 1.0 , NULL);
+      tab_double (t, 3, r, 0, intercept / df, NULL);
+      tab_double (t, 4, r, 0, F, NULL);
+      tab_double (t, 5, r, 0, gsl_cdf_fdist_Q (F, df, n_total - df_corr),
+                 NULL);
       r++;
     }
 
-  for (f = 0; f < cmd->n_factor_vars; ++f)
+  for (f = 0; f < cmd->n_interactions; ++f)
     {
-      tab_text (t, 0, r++, TAB_LEFT | TAT_TITLE,
-               var_to_string (cmd->factor_vars[f]));
+      struct string str = DS_EMPTY_INITIALIZER;
+      const double df = categoricals_df (ws->cats, f);
+      const double ssq = gsl_vector_get (ws->ssq, f + 1);
+      const double F = ssq / df / mse;
+      interaction_to_string (cmd->interactions[f], &str);
+      tab_text (t, 0, r, TAB_LEFT | TAT_TITLE, ds_cstr (&str));
+      ds_destroy (&str);
+
+      tab_double (t, 1, r, 0, ssq, NULL);
+      tab_double (t, 2, r, 0, df, wfmt);
+      tab_double (t, 3, r, 0, ssq / df, NULL);
+      tab_double (t, 4, r, 0, F, NULL);
+
+      tab_double (t, 5, r, 0, gsl_cdf_fdist_Q (F, df, n_total - df_corr),
+                 NULL);
+      r++;
     }
 
-  tab_text (t, 0, r++, TAB_LEFT | TAT_TITLE, _("Error"));
+  {
+    /* Corrected Model */
+    const double df = df_corr - 1.0;
+    const double ssq = ws->total_ssq - gsl_vector_get (ws->ssq, 0);
+    const double F = ssq / df / mse;
+    tab_double (t, 1, heading_rows, 0, ssq, NULL);
+    tab_double (t, 2, heading_rows, 0, df, wfmt);
+    tab_double (t, 3, heading_rows, 0, ssq / df, NULL);
+    tab_double (t, 4, heading_rows, 0, F, NULL);
+
+    tab_double (t, 5, heading_rows, 0,
+               gsl_cdf_fdist_Q (F, df, n_total - df_corr), NULL);
+  }
+
+  {
+    const double df = n_total - df_corr;
+    const double ssq = gsl_vector_get (ws->ssq, 0);
+    const double mse = ssq / df;
+    tab_text (t, 0, r, TAB_LEFT | TAT_TITLE, _("Error"));
+    tab_double (t, 1, r, 0, ssq, NULL);
+    tab_double (t, 2, r, 0, df, wfmt);
+    tab_double (t, 3, r++, 0, mse, NULL);
+  }
 
   if (cmd->intercept)
     {
-      double ssq = intercept + ws->total_ssq;
-      double mse = ssq / n_total;
+      const double intercept = pow2 (mean * n_total) / n_total;
+      const double ssq = intercept + ws->total_ssq;
+
       tab_text (t, 0, r, TAB_LEFT | TAT_TITLE, _("Total"));
       tab_double (t, 1, r, 0, ssq, NULL);
       tab_double (t, 2, r, 0, n_total, wfmt);
@@ -435,14 +642,16 @@ output_glm (struct glm_spec *cmd, const struct glm_workspace *ws)
 
   tab_text (t, 0, r, TAB_LEFT | TAT_TITLE, _("Corrected Total"));
 
+
   tab_double (t, 1, r, 0, ws->total_ssq, NULL);
   tab_double (t, 2, r, 0, n_total - 1.0, wfmt);
 
   tab_submit (t);
 }
 
-static 
-void dump_matrix (const gsl_matrix *m)
+#if 0
+static void
+dump_matrix (const gsl_matrix * m)
 {
   size_t i, j;
   for (i = 0; i < m->size1; ++i)
@@ -456,3 +665,127 @@ void dump_matrix (const gsl_matrix *m)
     }
   printf ("\n");
 }
+#endif
+
+
+\f
+
+/* Match a variable.
+   If the match succeeds, the variable will be placed in VAR.
+   Returns true if successful */
+static bool
+lex_match_variable (struct lexer *lexer, const struct glm_spec *glm, const struct variable **var)
+{
+  if (lex_token (lexer) !=  T_ID)
+    return false;
+
+  *var = parse_variable_const  (lexer, glm->dict);
+
+  if ( *var == NULL)
+    return false;
+  return true;
+}
+
+/* An interaction is a variable followed by {*, BY} followed by an interaction */
+static bool
+parse_design_interaction (struct lexer *lexer, struct glm_spec *glm, struct interaction **iact)
+{
+  const struct variable *v = NULL;
+  assert (iact);
+
+  switch  (lex_next_token (lexer, 1))
+    {
+    case T_ENDCMD:
+    case T_SLASH:
+    case T_COMMA:
+    case T_ID:
+    case T_BY:
+    case T_ASTERISK:
+      break;
+    default:
+      return false;
+      break;
+    }
+
+  if (! lex_match_variable (lexer, glm, &v))
+    {
+      interaction_destroy (*iact);
+      *iact = NULL;
+      return false;
+    }
+  
+  assert (v);
+
+  if ( *iact == NULL)
+    *iact = interaction_create (v);
+  else
+    interaction_add_variable (*iact, v);
+
+  if ( lex_match (lexer, T_ASTERISK) || lex_match (lexer, T_BY))
+    {
+      // lex_error (lexer, "Interactions are not yet implemented"); return false;
+      return parse_design_interaction (lexer, glm, iact);
+    }
+
+  return true;
+}
+
+static bool
+parse_nested_variable (struct lexer *lexer, struct glm_spec *glm)
+{
+  const struct variable *v = NULL;
+  if ( ! lex_match_variable (lexer, glm, &v))
+    return false;
+
+  if (lex_match (lexer, T_LPAREN))
+    {
+      if ( ! parse_nested_variable (lexer, glm))
+       return false;
+
+      if ( ! lex_force_match (lexer, T_RPAREN))
+       return false;
+    }
+
+  lex_error (lexer, "Nested variables are not yet implemented"); return false;  
+  return true;
+}
+
+/* A design term is an interaction OR a nested variable */
+static bool
+parse_design_term (struct lexer *lexer, struct glm_spec *glm)
+{
+  struct interaction *iact = NULL;
+  if (parse_design_interaction (lexer, glm, &iact))
+    {
+      /* Interaction parsing successful.  Add to list of interactions */
+      glm->interactions = xrealloc (glm->interactions, sizeof *glm->interactions * ++glm->n_interactions);
+      glm->interactions[glm->n_interactions - 1] = iact;
+      return true;
+    }
+
+  if ( parse_nested_variable (lexer, glm))
+    return true;
+
+  return false;
+}
+
+
+
+/* Parse a complete DESIGN specification.
+   A design spec is a design term, optionally followed by a comma,
+   and another design spec.
+*/
+static bool
+parse_design_spec (struct lexer *lexer, struct glm_spec *glm)
+{
+  if  (lex_token (lexer) == T_ENDCMD || lex_token (lexer) == T_SLASH)
+    return true;
+
+  if ( ! parse_design_term (lexer, glm))
+    return false;
+
+  lex_match (lexer, T_COMMA);
+
+  return parse_design_spec (lexer, glm);
+}
+
diff --git a/src/language/stats/ks-one-sample.c b/src/language/stats/ks-one-sample.c
new file mode 100644 (file)
index 0000000..aba2cbd
--- /dev/null
@@ -0,0 +1,401 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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 "language/stats/ks-one-sample.h"
+
+#include <gsl/gsl_cdf.h>
+#include <math.h>
+#include <stdlib.h>
+
+
+#include "math/sort.h"
+#include "data/case.h"
+#include "data/casereader.h"
+#include "data/dataset.h"
+#include "data/dictionary.h"
+#include "data/format.h"
+#include "data/value-labels.h"
+#include "data/variable.h"
+#include "language/stats/freq.h"
+#include "language/stats/npar.h"
+#include "libpspp/array.h"
+#include "libpspp/assertion.h"
+#include "libpspp/cast.h"
+#include "libpspp/compiler.h"
+#include "libpspp/hash-functions.h"
+#include "libpspp/message.h"
+#include "libpspp/misc.h"
+#include "output/tab.h"
+
+#include "gl/xalloc.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+
+/* The per test variable statistics */
+struct ks
+{
+  double obs_cc;
+
+  double test_min ;
+  double test_max;
+  double mu;
+  double sigma;
+
+  double diff_pos;
+  double diff_neg;
+
+  double ssq;
+  double sum;
+};
+
+typedef double theoretical (const struct ks *ks, double x);
+typedef theoretical *theoreticalfp;
+
+static double
+theoretical_uniform (const struct ks *ks, double x)
+{
+  return gsl_cdf_flat_P (x, ks->test_min, ks->test_max);
+}
+
+static double
+theoretical_normal (const struct ks *ks, double x)
+{
+  return gsl_cdf_gaussian_P (x - ks->mu, ks->sigma);
+}
+
+static double
+theoretical_poisson (const struct ks *ks, double x)
+{
+  return gsl_cdf_poisson_P (x, ks->mu);
+}
+
+static double
+theoretical_exponential (const struct ks *ks, double x)
+{
+  return gsl_cdf_exponential_P (x, 1/ks->mu);
+}
+
+
+static const  theoreticalfp theoreticalf[4] = 
+{
+  theoretical_normal,
+  theoretical_uniform,
+  theoretical_poisson,
+  theoretical_exponential
+};
+
+/* 
+   Return the assymptotic approximation to the significance of Z
+ */
+static double
+ks_asymp_sig (double z)
+{
+  if (z < 0.27)
+    return 1;
+  
+  if (z >= 3.1)
+    return 0;
+
+  if (z < 1)
+    {
+      double q = exp (-1.233701 * pow (z, -2));
+      return 1 - 2.506628 * (q + pow (q, 9) + pow (q, 25))/ z ;
+    }
+  else
+    {
+      double q = exp (-2 * z * z);
+      return 2 * (q - pow (q, 4) + pow (q, 9) - pow (q, 16))/ z ;
+    }
+}
+
+static void show_results (const struct ks *, const struct ks_one_sample_test *,  const struct fmt_spec *);
+
+
+void
+ks_one_sample_execute (const struct dataset *ds,
+                  struct casereader *input,
+                   enum mv_class exclude,
+                  const struct npar_test *test)
+{
+  const struct dictionary *dict = dataset_dict (ds);
+  const struct ks_one_sample_test *kst = UP_CAST (test, const struct ks_one_sample_test, parent.parent);
+  const struct one_sample_test *ost = &kst->parent;
+  struct ccase *c;
+  const struct variable *wvar = dict_get_weight (dict);
+  const struct fmt_spec *wfmt = wvar ? var_get_print_format (wvar) : & F_8_0;
+  bool warn = true;
+  int v;
+
+  struct ks *ks = xcalloc (sizeof *ks, ost->n_vars);
+
+  for (v = 0; v < ost->n_vars; ++v)
+    {
+      ks[v].obs_cc = 0;
+      ks[v].test_min = DBL_MAX;
+      ks[v].test_max = -DBL_MAX;
+      ks[v].diff_pos = -DBL_MAX;
+      ks[v].diff_neg = DBL_MAX;
+      ks[v].sum = 0;
+      ks[v].ssq = 0;
+    }
+
+  struct casereader *r = casereader_clone (input);
+
+  for (; (c = casereader_read (r)) != NULL; case_unref (c))
+    {
+      const double weight = dict_get_case_weight (dict, c, &warn);
+
+      for (v = 0; v < ost->n_vars; ++v)
+       {
+         const struct variable *var = ost->vars[v];
+         const union value *val = case_data (c, var);
+      
+         if (var_is_value_missing (var, val, exclude))
+           continue;
+
+         minimize (&ks[v].test_min, val->f);
+         maximize (&ks[v].test_max, val->f);
+
+         ks[v].obs_cc += weight;
+         ks[v].sum += val->f;
+         ks[v].ssq += pow2 (val->f);
+       }
+    }
+  casereader_destroy (r);
+
+  for (v = 0; v < ost->n_vars; ++v)
+    {
+      switch (kst->dist)
+       {
+       case KS_UNIFORM:
+         if (kst->p[0] != SYSMIS)
+           ks[v].test_min = kst->p[0];
+
+         if (kst->p[1] != SYSMIS)
+           ks[v].test_max = kst->p[1];
+         break;
+       case KS_NORMAL:
+         if (kst->p[0] != SYSMIS)
+           ks[v].mu = kst->p[0];
+         else
+           ks[v].mu = ks[v].sum / ks[v].obs_cc;
+
+         if (kst->p[1] != SYSMIS)
+           ks[v].sigma = kst->p[1];
+         else
+           {
+             ks[v].sigma = ks[v].ssq - pow2 (ks[v].sum) / ks[v].obs_cc;
+             ks[v].sigma /= ks[v].obs_cc - 1;
+             ks[v].sigma = sqrt (ks[v].sigma);
+           }
+
+         break;
+       case KS_POISSON:
+       case KS_EXPONENTIAL:
+         if (kst->p[0] != SYSMIS)
+           ks[v].mu = ks[v].sigma = kst->p[0];
+         else 
+           ks[v].mu = ks[v].sigma = ks[v].sum / ks[v].obs_cc;
+         break;
+       default:
+         NOT_REACHED ();
+       }
+
+      const struct variable *var = ost->vars[v];
+      double cc = 0;
+      double prev_empirical = 0;
+      r = sort_execute_1var (casereader_clone (input), var);
+      for (; (c = casereader_read (r)) != NULL; case_unref (c))
+       {
+         double theoretical, empirical;
+         double d, dp;
+         const double weight = dict_get_case_weight (dict, c, &warn);
+         const union value *val = case_data (c, var);
+
+         if (var_is_value_missing (var, val, exclude))
+           continue;
+
+         cc += weight;
+
+         empirical = cc / ks[v].obs_cc;
+      
+         theoretical = theoreticalf[kst->dist] (&ks[v], val->f);
+      
+         d = empirical - theoretical;
+         dp = prev_empirical - theoretical;
+
+         if (d > 0)
+           maximize (&ks[v].diff_pos, d); 
+         else
+           minimize (&ks[v].diff_neg, d);
+
+         if (dp > 0)
+           maximize (&ks[v].diff_pos, dp); 
+         else
+           minimize (&ks[v].diff_neg, dp);
+
+         prev_empirical = empirical;
+       }
+
+      casereader_destroy (r);
+    }
+
+  show_results (ks, kst, wfmt);
+
+  free (ks);
+  casereader_destroy (input);
+}
+
+
+static void
+show_results (const struct ks *ks,
+             const struct ks_one_sample_test *kst,
+             const struct fmt_spec *wfmt)
+{
+  int i;
+  const int row_headers = 1;
+  const int column_headers = 2;
+  const int nc = kst->parent.n_vars + column_headers;
+  const int nr = 8 + row_headers;
+  struct tab_table *table = tab_create (nc, nr);
+
+  tab_headers (table, row_headers, 0, column_headers, 0);
+
+  tab_title (table, _("One-Sample Kolmogorov-Smirnov Test"));
+
+  /* Box around the table */
+  tab_box (table, TAL_2, TAL_2, -1, -1,
+          0,  0, nc - 1, nr - 1 );
+
+  tab_hline (table, TAL_2, 0, nc - 1, row_headers);
+
+  tab_vline (table, TAL_1, column_headers, 0, nr - 1);
+
+  tab_text (table,  0, 1,
+           TAT_TITLE | TAB_LEFT , _("N"));
+
+  switch (kst->dist)
+    {
+    case KS_NORMAL:
+      tab_text (table,  0, 2,
+               TAT_TITLE | TAB_LEFT , _("Normal Parameters"));
+      
+      tab_text (table,  1, 2,
+               TAT_TITLE | TAB_LEFT , _("Mean"));
+      tab_text (table,  1, 3,
+               TAT_TITLE | TAB_LEFT , _("Std. Deviation"));
+      break;
+    case KS_UNIFORM:
+      tab_text (table,  0, 2,
+               TAT_TITLE | TAB_LEFT , _("Uniform Parameters"));
+      
+      tab_text (table,  1, 2,
+               TAT_TITLE | TAB_LEFT , _("Minimum"));
+      tab_text (table,  1, 3,
+               TAT_TITLE | TAB_LEFT , _("Maximum"));
+      break;
+    case KS_POISSON:
+      tab_text (table,  0, 2,
+               TAT_TITLE | TAB_LEFT , _("Poisson Parameters"));
+      
+      tab_text (table,  1, 2,
+               TAT_TITLE | TAB_LEFT , _("Lambda"));
+      break;
+    case KS_EXPONENTIAL:
+      tab_text (table,  0, 2,
+               TAT_TITLE | TAB_LEFT , _("Exponential Parameters"));
+      
+      tab_text (table,  1, 2,
+               TAT_TITLE | TAB_LEFT , _("Scale"));
+      break;
+
+    default:
+      NOT_REACHED ();
+    }
+
+  /* The variable columns */
+  for (i = 0; i < kst->parent.n_vars; ++i)
+    {
+      double abs = 0;
+      double z = 0;
+      const int col = 2 + i;
+      tab_text (table, col, 0,
+               TAT_TITLE | TAB_CENTER , 
+               var_to_string (kst->parent.vars[i]));
+
+      switch (kst->dist)
+       {
+       case KS_UNIFORM:
+         tab_double (table, col, 1, 0, ks[i].obs_cc, wfmt);
+         tab_double (table, col, 2, 0, ks[i].test_min, NULL);
+         tab_double (table, col, 3, 0, ks[i].test_max, NULL);
+         break;
+
+       case KS_NORMAL:
+         tab_double (table, col, 1, 0, ks[i].obs_cc, wfmt);
+         tab_double (table, col, 2, 0, ks[i].mu, NULL);
+         tab_double (table, col, 3, 0, ks[i].sigma, NULL);
+         break;
+
+       case KS_POISSON:
+       case KS_EXPONENTIAL:
+         tab_double (table, col, 1, 0, ks[i].obs_cc, wfmt);
+         tab_double (table, col, 2, 0, ks[i].mu, NULL);
+         break;
+
+       default:
+         NOT_REACHED ();
+       }
+
+      abs = ks[i].diff_pos;
+      maximize (&abs, -ks[i].diff_neg);
+
+      z = sqrt (ks[i].obs_cc) * abs;
+
+      tab_double (table, col, 5, 0, ks[i].diff_pos, NULL);
+      tab_double (table, col, 6, 0, ks[i].diff_neg, NULL);
+
+      tab_double (table, col, 4, 0, abs, NULL);
+
+      tab_double (table, col, 7, 0, z, NULL);
+      tab_double (table, col, 8, 0, ks_asymp_sig (z), NULL);
+    }
+
+
+  tab_text (table,  0, 4,
+           TAT_TITLE | TAB_LEFT , _("Most Extreme Differences"));
+
+  tab_text (table,  1, 4,
+           TAT_TITLE | TAB_LEFT , _("Absolute"));
+
+  tab_text (table,  1, 5,
+           TAT_TITLE | TAB_LEFT , _("Positive"));
+
+  tab_text (table,  1, 6,
+           TAT_TITLE | TAB_LEFT , _("Negative"));
+
+  tab_text (table,  0, 7,
+           TAT_TITLE | TAB_LEFT , _("Kolmogorov-Smirnov Z"));
+
+  tab_text (table,  0, 8,
+           TAT_TITLE | TAB_LEFT , _("Asymp. Sig. (2-tailed)"));
+
+  tab_submit (table);
+}
diff --git a/src/language/stats/ks-one-sample.h b/src/language/stats/ks-one-sample.h
new file mode 100644 (file)
index 0000000..054cce4
--- /dev/null
@@ -0,0 +1,49 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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/>. */
+
+#if !ks_one_sample_h
+#define ks_one_sample_h 1
+
+#include <stddef.h>
+#include <stdbool.h>
+#include "language/stats/npar.h"
+
+enum dist
+  {
+    KS_NORMAL,
+    KS_UNIFORM,
+    KS_POISSON,
+    KS_EXPONENTIAL
+  };
+
+struct ks_one_sample_test
+{
+  struct one_sample_test parent;
+
+  double p[2];
+  enum dist dist;
+};
+
+struct casereader;
+struct dataset;
+
+
+void ks_one_sample_execute (const struct dataset *ds,
+                           struct casereader *input,
+                           enum mv_class exclude,
+                           const struct npar_test *test);
+
+#endif
diff --git a/src/language/stats/mcnemar.c b/src/language/stats/mcnemar.c
new file mode 100644 (file)
index 0000000..53e9a52
--- /dev/null
@@ -0,0 +1,295 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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 "mcnemar.h"
+
+#include <gsl/gsl_cdf.h>
+#include <gsl/gsl_randist.h>
+
+#include "data/casereader.h"
+#include "data/dataset.h"
+#include "data/dictionary.h"
+#include "data/format.h"
+#include "data/missing-values.h"
+#include "data/variable.h"
+#include "language/stats/npar.h"
+#include "libpspp/str.h"
+#include "output/tab.h"
+#include "libpspp/message.h"
+#include "gl/minmax.h"
+#include "gl/xalloc.h"
+
+#include "data/value.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+
+struct mcnemar
+{
+  union value val0;
+  union value val1;
+
+  double n00;
+  double n01;
+  double n10;
+  double n11;
+};
+
+static void
+output_freq_table (variable_pair *vp,
+                  const struct mcnemar *param,
+                  const struct dictionary *dict);
+
+
+static void
+output_statistics_table (const struct two_sample_test *t2s,
+                        const struct mcnemar *param,
+                        const struct dictionary *dict);
+
+
+void
+mcnemar_execute (const struct dataset *ds,
+                 struct casereader *input,
+                 enum mv_class exclude,
+                 const struct npar_test *test,
+                 bool exact UNUSED,
+                 double timer UNUSED)
+{
+  int i;
+  bool warn = true;
+
+  const struct dictionary *dict = dataset_dict (ds);
+
+  const struct two_sample_test *t2s = UP_CAST (test, const struct two_sample_test, parent);
+  struct ccase *c;
+  
+  struct casereader *r = input;
+
+  struct mcnemar *mc = xcalloc (sizeof *mc, t2s->n_pairs);
+
+  for (i = 0 ; i < t2s->n_pairs; ++i )
+    {
+      mc[i].val0.f = mc[i].val1.f = SYSMIS;
+    }
+
+  for (; (c = casereader_read (r)) != NULL; case_unref (c))
+    {
+      const double weight = dict_get_case_weight (dict, c, &warn);
+
+      for (i = 0 ; i < t2s->n_pairs; ++i )
+       {
+         variable_pair *vp = &t2s->pairs[i];
+         const union value *value0 = case_data (c, (*vp)[0]);
+         const union value *value1 = case_data (c, (*vp)[1]);
+
+         if (var_is_value_missing ((*vp)[0], value0, exclude))
+           continue;
+
+         if (var_is_value_missing ((*vp)[1], value1, exclude))
+           continue;
+
+
+         if ( mc[i].val0.f == SYSMIS)
+           {
+             if (mc[i].val1.f != value0->f)
+               mc[i].val0.f = value0->f;
+             else if (mc[i].val1.f != value1->f)
+               mc[i].val0.f = value1->f;
+           }
+
+         if ( mc[i].val1.f == SYSMIS)
+           {
+             if (mc[i].val0.f != value1->f)
+               mc[i].val1.f = value1->f;
+             else if (mc[i].val0.f != value0->f)
+               mc[i].val1.f = value0->f;
+           }
+
+         if (mc[i].val0.f == value0->f && mc[i].val0.f == value1->f)
+           {
+             mc[i].n00 += weight;
+           }
+         else if ( mc[i].val0.f == value0->f && mc[i].val1.f == value1->f)
+           {
+             mc[i].n10 += weight;
+           }
+         else if ( mc[i].val1.f == value0->f && mc[i].val0.f == value1->f)
+           {
+             mc[i].n01 += weight;
+           }
+         else if ( mc[i].val1.f == value0->f && mc[i].val1.f == value1->f)
+           {
+             mc[i].n11 += weight;
+           }
+         else
+           {
+             msg (ME, _("The McNemar test is appropriate only for dichotomous variables"));
+           }
+       }
+    }
+
+  casereader_destroy (r);
+
+  for (i = 0 ; i < t2s->n_pairs ; ++i)
+    output_freq_table (&t2s->pairs[i], mc + i, dict);
+
+  output_statistics_table (t2s, mc, dict);
+
+  free (mc);
+}
+
+
+static void
+output_freq_table (variable_pair *vp,
+                  const struct mcnemar *param,
+                  const struct dictionary *dict)
+{
+  const int header_rows = 2;
+  const int header_cols = 1;
+
+  struct tab_table *table = tab_create (header_cols + 2, header_rows + 2);
+
+  const struct variable *wv = dict_get_weight (dict);
+  const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0;
+
+
+  struct string pair_name;
+  struct string val1str ;
+  struct string val0str ;
+
+  ds_init_empty (&val0str);
+  ds_init_empty (&val1str);
+  
+  var_append_value_name ((*vp)[0], &param->val0, &val0str);
+  var_append_value_name ((*vp)[1], &param->val1, &val1str);
+
+  ds_init_cstr (&pair_name, var_to_string ((*vp)[0]));
+  ds_put_cstr (&pair_name, " & ");
+  ds_put_cstr (&pair_name, var_to_string ((*vp)[1]));
+
+  tab_title (table, ds_cstr (&pair_name));
+
+  ds_destroy (&pair_name);
+
+  tab_headers (table, header_cols, 0, header_rows, 0);
+
+  /* Vertical lines inside the box */
+  tab_box (table, 0, 0, -1, TAL_1,
+          1, 0, tab_nc (table) - 1, tab_nr (table) - 1 );
+
+  /* Box around entire table */
+  tab_box (table, TAL_2, TAL_2, -1, -1,
+          0, 0, tab_nc (table) - 1, tab_nr (table) - 1 );
+
+  tab_vline (table, TAL_2, header_cols, 0, tab_nr (table) - 1);
+  tab_hline (table, TAL_2, 0, tab_nc (table) - 1, header_rows);
+
+  tab_text (table,  0, 0,  TAB_CENTER, var_to_string ((*vp)[0]));
+
+  tab_joint_text (table,  1, 0,  2, 0, TAB_CENTER, var_to_string ((*vp)[1]));
+  tab_hline (table, TAL_1, 1, tab_nc (table) - 1, 1);
+
+
+  tab_text (table, 0, header_rows + 0, TAB_LEFT, ds_cstr (&val0str));
+  tab_text (table, 0, header_rows + 1, TAB_LEFT, ds_cstr (&val1str));
+
+  tab_text (table, header_cols + 0, 1, TAB_LEFT, ds_cstr (&val0str));
+  tab_text (table, header_cols + 1, 1, TAB_LEFT, ds_cstr (&val1str));
+
+  tab_double (table, header_cols + 0, header_rows + 0, TAB_RIGHT, param->n00, wfmt);
+  tab_double (table, header_cols + 0, header_rows + 1, TAB_RIGHT, param->n01, wfmt);
+  tab_double (table, header_cols + 1, header_rows + 0, TAB_RIGHT, param->n10, wfmt);
+  tab_double (table, header_cols + 1, header_rows + 1, TAB_RIGHT, param->n11, wfmt);
+
+  tab_submit (table);
+
+  ds_destroy (&val0str);
+  ds_destroy (&val1str);
+}
+
+
+static void
+output_statistics_table (const struct two_sample_test *t2s,
+                        const struct mcnemar *mc,
+                        const struct dictionary *dict)
+{
+  int i;
+
+  struct tab_table *table = tab_create (5, t2s->n_pairs + 1);
+
+  const struct variable *wv = dict_get_weight (dict);
+  const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0;
+
+  tab_title (table, _("Test Statistics"));
+
+  tab_headers (table, 0, 1,  0, 1);
+
+  tab_hline (table, TAL_2, 0, tab_nc (table) - 1, 1);
+  tab_vline (table, TAL_2, 1, 0, tab_nr (table) - 1);
+
+
+  /* Vertical lines inside the box */
+  tab_box (table, -1, -1, -1, TAL_1,
+          0, 0,
+          tab_nc (table) - 1, tab_nr (table) - 1);
+
+  /* Box around entire table */
+  tab_box (table, TAL_2, TAL_2, -1, -1,
+          0, 0, tab_nc (table) - 1,
+          tab_nr (table) - 1);
+
+  tab_text (table,  1, 0, TAT_TITLE | TAB_CENTER,
+           _("N"));
+
+  tab_text (table,  2, 0, TAT_TITLE | TAB_CENTER,
+           _("Exact Sig. (2-tailed)"));
+
+  tab_text (table,  3, 0, TAT_TITLE | TAB_CENTER,
+           _("Exact Sig. (1-tailed)"));
+
+  tab_text (table,  4, 0, TAT_TITLE | TAB_CENTER,
+           _("Point Probability"));
+
+  for (i = 0 ; i < t2s->n_pairs; ++i)
+    {
+      double sig;
+      variable_pair *vp = &t2s->pairs[i];
+
+      struct string pair_name;
+      ds_init_cstr (&pair_name, var_to_string ((*vp)[0]));
+      ds_put_cstr (&pair_name, " & ");
+      ds_put_cstr (&pair_name, var_to_string ((*vp)[1]));
+
+      tab_text (table,  0, 1 + i, TAB_LEFT, ds_cstr (&pair_name));
+      ds_destroy (&pair_name);
+
+      tab_double (table, 1, 1 + i, TAB_RIGHT, mc[i].n00 + mc[i].n01 + mc[i].n10 + mc[i].n11, wfmt);
+
+      sig = gsl_cdf_binomial_P (mc[i].n01,  0.5,  mc[i].n01 + mc[i].n10);
+
+      tab_double (table, 2, 1 + i, TAB_RIGHT, 2 * sig, NULL);
+      tab_double (table, 3, 1 + i, TAB_RIGHT, sig, NULL);
+
+      tab_double (table, 4, 1 + i, TAB_RIGHT, gsl_ran_binomial_pdf (mc[i].n01, 0.5, mc[i].n01 + mc[i].n10),
+                 NULL);
+    }
+
+  tab_submit (table);
+}
diff --git a/src/language/stats/mcnemar.h b/src/language/stats/mcnemar.h
new file mode 100644 (file)
index 0000000..41724a3
--- /dev/null
@@ -0,0 +1,35 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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/>. */
+
+#if !mcnemar_h
+#define mcnemar_h 1
+
+
+#include <stdbool.h>
+#include "data/missing-values.h"
+
+struct casereader;
+struct dataset;
+struct npar_test;
+
+void mcnemar_execute (const struct dataset *ds,
+                  struct casereader *input,
+                  enum mv_class exclude,
+                  const struct npar_test *test,
+                  bool exact,
+                  double timer);
+
+#endif
index 2bc42934a381b9798f18a0b1142524fd967445d3..bfeaf8f76fd67c90efb75390fca1bd9f1bb6311b 100644 (file)
 #include "language/lexer/variable-parser.h"
 #include "language/stats/binomial.h"
 #include "language/stats/chisquare.h"
+#include "language/stats/ks-one-sample.h"
 #include "language/stats/cochran.h"
 #include "language/stats/friedman.h"
 #include "language/stats/kruskal-wallis.h"
 #include "language/stats/mann-whitney.h"
+#include "language/stats/mcnemar.h"
 #include "language/stats/npar-summary.h"
 #include "language/stats/runs.h"
 #include "language/stats/sign.h"
@@ -82,6 +84,7 @@ struct cmd_npar_tests
     int chisquare;
     int cochran;
     int binomial;
+    int ks_one_sample;
     int wilcoxon;
     int sign;
     int runs;
@@ -89,6 +92,7 @@ struct cmd_npar_tests
     int kendall;
     int kruskal_wallis;
     int mann_whitney;
+    int mcnemar;
     int missing;
     int method;
     int statistics;
@@ -124,6 +128,7 @@ struct npar_specs
 /* Prototype for custom subcommands of NPAR TESTS. */
 static int npar_chisquare (struct lexer *, struct dataset *, struct npar_specs *);
 static int npar_binomial (struct lexer *, struct dataset *,  struct npar_specs *);
+static int npar_ks_one_sample (struct lexer *, struct dataset *, struct npar_specs *);
 static int npar_runs (struct lexer *, struct dataset *, struct npar_specs *);
 static int npar_friedman (struct lexer *, struct dataset *, struct npar_specs *);
 static int npar_kendall (struct lexer *, struct dataset *, struct npar_specs *);
@@ -132,6 +137,7 @@ static int npar_wilcoxon (struct lexer *, struct dataset *, struct npar_specs *)
 static int npar_sign (struct lexer *, struct dataset *, struct npar_specs *);
 static int npar_kruskal_wallis (struct lexer *, struct dataset *, struct npar_specs *);
 static int npar_mann_whitney (struct lexer *, struct dataset *, struct npar_specs *);
+static int npar_mcnemar (struct lexer *, struct dataset *, struct npar_specs *);
 static int npar_method (struct lexer *, struct npar_specs *);
 
 /* Command parsing functions. */
@@ -144,10 +150,12 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests
 {
   npt->binomial = 0;
   npt->chisquare = 0;
+  npt->ks_one_sample = 0;
   npt->cochran = 0;
   npt->friedman = 0;
   npt->kruskal_wallis = 0;
   npt->mann_whitney = 0;
+  npt->mcnemar = 0;
   npt->runs = 0;
   npt->sign = 0;
   npt->wilcoxon = 0;
@@ -258,6 +266,24 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests
               NOT_REACHED ();
             }
         }
+      else if (lex_match_phrase (lexer, "K-S") ||
+              lex_match_phrase (lexer, "KOLMOGOROV-SMIRNOV"))
+        {
+          lex_match (lexer, T_EQUALS);
+          npt->ks_one_sample++;
+          switch (npar_ks_one_sample (lexer, ds, nps))
+            {
+            case 0:
+              goto lossage;
+            case 1:
+              break;
+            case 2:
+              lex_error (lexer, NULL);
+              goto lossage;
+            default:
+              NOT_REACHED ();
+            }
+        }
       else if (lex_match_phrase (lexer, "K-W") ||
               lex_match_phrase (lexer, "KRUSKAL-WALLIS"))
         {
@@ -276,6 +302,23 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests
               NOT_REACHED ();
             }
         }
+      else if (lex_match_phrase (lexer, "MCNEMAR"))
+        {
+          lex_match (lexer, T_EQUALS);
+          npt->mcnemar++;
+          switch (npar_mcnemar (lexer, ds, nps))
+            {
+            case 0:
+              goto lossage;
+            case 1:
+              break;
+            case 2:
+              lex_error (lexer, NULL);
+              goto lossage;
+            default:
+              NOT_REACHED ();
+            }
+        }
       else if (lex_match_phrase (lexer, "M-W") ||
               lex_match_phrase (lexer, "MANN-WHITNEY"))
         {
@@ -888,20 +931,93 @@ npar_binomial (struct lexer *lexer, struct dataset *ds,
 }
 
 
-static bool
-parse_two_sample_related_test (struct lexer *lexer,
-                                   const struct dictionary *dict,
-                                   struct two_sample_test *test_parameters,
-                                   struct pool *pool
-                                   );
+
+static void
+ks_one_sample_parse_params (struct lexer *lexer, struct ks_one_sample_test *kst, int params)
+{
+  assert (params == 1 || params == 2);
+
+  if (lex_is_number (lexer))
+    {
+      kst->p[0] = lex_number (lexer);
+
+      lex_get (lexer);
+      if ( params == 2)
+       {
+         lex_match (lexer, T_COMMA);
+         if (lex_force_num (lexer))
+           {
+             kst->p[1] = lex_number (lexer);
+             lex_get (lexer);
+           }
+       }
+    }
+}
+
+static int
+npar_ks_one_sample (struct lexer *lexer, struct dataset *ds, struct npar_specs *specs)
+{
+  struct ks_one_sample_test *kst = pool_alloc (specs->pool, sizeof (*kst));
+  struct one_sample_test *tp = &kst->parent;
+  struct npar_test *nt = &tp->parent;
+
+  nt->execute = ks_one_sample_execute;
+  nt->insert_variables = one_sample_insert_variables;
+
+  kst->p[0] = kst->p[1] = SYSMIS;
+
+  if (! lex_force_match (lexer, T_LPAREN))
+    return 2;
+
+  if (lex_match_id (lexer, "NORMAL"))
+    {
+      kst->dist = KS_NORMAL;
+      ks_one_sample_parse_params (lexer, kst, 2);
+    }
+  else if (lex_match_id (lexer, "POISSON"))
+    {
+      kst->dist = KS_POISSON;
+      ks_one_sample_parse_params (lexer, kst, 1);
+    }
+  else if (lex_match_id (lexer, "UNIFORM"))
+    {
+      kst->dist = KS_UNIFORM;
+      ks_one_sample_parse_params (lexer, kst, 2);
+    }
+  else if (lex_match_id (lexer, "EXPONENTIAL"))
+    {
+      kst->dist = KS_EXPONENTIAL;
+      ks_one_sample_parse_params (lexer, kst, 1);
+    }
+  else
+    return 2;
+
+  if (! lex_force_match (lexer, T_RPAREN))
+    return 2;
+
+  lex_match (lexer, T_EQUALS);
+
+  if (! parse_variables_const_pool (lexer, specs->pool, dataset_dict (ds),
+                                 &tp->vars, &tp->n_vars,
+                                 PV_NUMERIC | PV_NO_SCRATCH | PV_NO_DUPLICATE) )
+    return 2;
+
+  specs->n_tests++;
+  specs->test = pool_realloc (specs->pool,
+                             specs->test,
+                             sizeof (*specs->test) * specs->n_tests);
+
+  specs->test[specs->n_tests - 1] = kst;
+
+  return 1;
+}
 
 
 static bool
 parse_two_sample_related_test (struct lexer *lexer,
                               const struct dictionary *dict,
                               struct two_sample_test *test_parameters,
-                              struct pool *pool
-                              )
+                              struct pool *pool)
 {
   int n = 0;
   bool paired = false;
@@ -965,8 +1081,8 @@ parse_two_sample_related_test (struct lexer *lexer,
          assert (n_vlist1 == n_vlist2);
          for ( i = 0 ; i < n_vlist1; ++i )
            {
-             test_parameters->pairs[n][1] = vlist1[i];
-             test_parameters->pairs[n][0] = vlist2[i];
+             test_parameters->pairs[n][0] = vlist1[i];
+             test_parameters->pairs[n][1] = vlist2[i];
              n++;
            }
        }
@@ -977,8 +1093,8 @@ parse_two_sample_related_test (struct lexer *lexer,
            {
              for ( j = 0 ; j < n_vlist2; ++j )
                {
-                 test_parameters->pairs[n][1] = vlist1[i];
-                 test_parameters->pairs[n][0] = vlist2[j];
+                 test_parameters->pairs[n][0] = vlist1[i];
+                 test_parameters->pairs[n][1] = vlist2[j];
                  n++;
                }
            }
@@ -992,8 +1108,8 @@ parse_two_sample_related_test (struct lexer *lexer,
          for ( j = i + 1 ; j < n_vlist1; ++j )
            {
              assert ( n < test_parameters->n_pairs);
-             test_parameters->pairs[n][1] = vlist1[i];
-             test_parameters->pairs[n][0] = vlist1[j];
+             test_parameters->pairs[n][0] = vlist1[i];
+             test_parameters->pairs[n][1] = vlist1[j];
              n++;
            }
        }
@@ -1053,8 +1169,6 @@ npar_wilcoxon (struct lexer *lexer,
               struct dataset *ds,
               struct npar_specs *specs )
 {
-
-
   struct two_sample_test *tp = pool_alloc (specs->pool, sizeof (*tp));
   struct npar_test *nt = &tp->parent;
   nt->execute = wilcoxon_execute;
@@ -1098,6 +1212,8 @@ npar_mann_whitney (struct lexer *lexer,
 }
 
 
+
+
 static int
 npar_sign (struct lexer *lexer, struct dataset *ds,
           struct npar_specs *specs)
@@ -1120,6 +1236,30 @@ npar_sign (struct lexer *lexer, struct dataset *ds,
   return 1;
 }
 
+
+static int
+npar_mcnemar (struct lexer *lexer, struct dataset *ds,
+          struct npar_specs *specs)
+{
+  struct two_sample_test *tp = pool_alloc (specs->pool, sizeof (*tp));
+  struct npar_test *nt = &tp->parent;
+
+  nt->execute = mcnemar_execute;
+
+  if (!parse_two_sample_related_test (lexer, dataset_dict (ds),
+                                     tp, specs->pool) )
+    return 0;
+
+  specs->n_tests++;
+  specs->test = pool_realloc (specs->pool,
+                             specs->test,
+                             sizeof (*specs->test) * specs->n_tests);
+  specs->test[specs->n_tests - 1] = nt;
+
+  return 1;
+}
+
+
 static int
 npar_kruskal_wallis (struct lexer *lexer, struct dataset *ds,
                      struct npar_specs *specs)
index a63d1a29e532876ebadb1fbf4d2f8100e0f83021..8182d51780abf1e501bbd6374ed3a9f52d5842da 100644 (file)
@@ -37,7 +37,9 @@
 #include "libpspp/misc.h"
 #include "libpspp/taint.h"
 #include "linreg/sweep.h"
+#include "tukey/tukey.h"
 #include "math/categoricals.h"
+#include "math/interaction.h"
 #include "math/covariance.h"
 #include "math/levene.h"
 #include "math/moments.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
 
+/* Workspace variable for each dependent variable */
+struct per_var_ws
+{
+  struct categoricals *cat;
+  struct covariance *cov;
+  struct levene *nl;
+
+  double n;
+
+  double sst;
+  double sse;
+  double ssa;
+
+  int n_groups;
+
+  double mse;
+};
+
+/* Per category data */
+struct descriptive_data
+{
+  const struct variable *var;
+  struct moments1 *mom;
+
+  double minimum;
+  double maximum;
+};
 
 enum missing_type
   {
@@ -70,8 +100,28 @@ struct contrasts_node
 {
   struct ll ll; 
   struct ll_list coefficient_list;
+};
+
+
+struct oneway_spec;
+
+typedef double df_func (const struct per_var_ws *pvw, const struct moments1 *mom_i, const struct moments1 *mom_j);
+typedef double ts_func (int k, const struct moments1 *mom_i, const struct moments1 *mom_j, double std_err);
+typedef double p1tail_func (double ts, double df1, double df2);
+
+typedef double pinv_func (double std_err, double alpha, double df, int k, const struct moments1 *mom_i, const struct moments1 *mom_j);
+
 
-  bool bad_count; /* True if the number of coefficients does not equal the number of groups */
+struct posthoc
+{
+  const char *syntax;
+  const char *label;
+
+  df_func *dff;
+  ts_func *tsf;
+  p1tail_func *p1f;
+
+  pinv_func *pinv;
 };
 
 struct oneway_spec
@@ -92,33 +142,209 @@ struct oneway_spec
   /* The weight variable */
   const struct variable *wv;
 
+  /* The confidence level for multiple comparisons */
+  double alpha;
+
+  int *posthoc;
+  int n_posthoc;
 };
 
-/* Per category data */
-struct descriptive_data
+static double
+df_common (const struct per_var_ws *pvw, const struct moments1 *mom_i UNUSED, const struct moments1 *mom_j UNUSED)
 {
-  const struct variable *var;
-  struct moments1 *mom;
+  return  pvw->n - pvw->n_groups;
+}
 
-  double minimum;
-  double maximum;
-};
+static double
+df_individual (const struct per_var_ws *pvw UNUSED, const struct moments1 *mom_i, const struct moments1 *mom_j)
+{
+  double n_i, var_i;
+  double n_j, var_j;
+  double nom,denom;
 
-/* Workspace variable for each dependent variable */
-struct per_var_ws
+  moments1_calculate (mom_i, &n_i, NULL, &var_i, 0, 0);  
+  moments1_calculate (mom_j, &n_j, NULL, &var_j, 0, 0);
+
+  nom = pow2 (var_i/n_i + var_j/n_j);
+  denom = pow2 (var_i/n_i) / (n_i - 1) + pow2 (var_j/n_j) / (n_j - 1);
+
+  return nom / denom;
+}
+
+static double lsd_pinv (double std_err, double alpha, double df, int k UNUSED, const struct moments1 *mom_i UNUSED, const struct moments1 *mom_j UNUSED)
 {
-  struct categoricals *cat;
-  struct covariance *cov;
+  return std_err * gsl_cdf_tdist_Pinv (1.0 - alpha / 2.0, df);
+}
 
-  double sst;
-  double sse;
-  double ssa;
+static double bonferroni_pinv (double std_err, double alpha, double df, int k, const struct moments1 *mom_i UNUSED, const struct moments1 *mom_j UNUSED)
+{
+  const int m = k * (k - 1) / 2;
+  return std_err * gsl_cdf_tdist_Pinv (1.0 - alpha / (2.0 * m), df);
+}
 
-  int n_groups;
+static double sidak_pinv (double std_err, double alpha, double df, int k, const struct moments1 *mom_i UNUSED, const struct moments1 *mom_j UNUSED)
+{
+  const double m = k * (k - 1) / 2;
+  double lp = 1.0 - exp (log (1.0 - alpha) / m ) ;
+  return std_err * gsl_cdf_tdist_Pinv (1.0 - lp / 2.0, df);
+}
+
+static double tukey_pinv (double std_err, double alpha, double df, int k, const struct moments1 *mom_i UNUSED, const struct moments1 *mom_j UNUSED)
+{
+  return std_err / sqrt (2.0)  * qtukey (1 - alpha, 1.0, k, df, 1, 0);
+}
+
+static double scheffe_pinv (double std_err, double alpha, double df, int k, const struct moments1 *mom_i UNUSED, const struct moments1 *mom_j UNUSED)
+{
+  double x = (k - 1) * gsl_cdf_fdist_Pinv (1.0 - alpha, k - 1, df);
+  return std_err * sqrt (x);
+}
+
+static double gh_pinv (double std_err UNUSED, double alpha, double df, int k, const struct moments1 *mom_i, const struct moments1 *mom_j)
+{
+  double n_i, mean_i, var_i;
+  double n_j, mean_j, var_j;
+  double m;
+
+  moments1_calculate (mom_i, &n_i, &mean_i, &var_i, 0, 0);  
+  moments1_calculate (mom_j, &n_j, &mean_j, &var_j, 0, 0);
+
+  m = sqrt ((var_i/n_i + var_j/n_j) / 2.0);
+
+  return m * qtukey (1 - alpha, 1.0, k, df, 1, 0);
+}
+
+
+static double 
+multiple_comparison_sig (double std_err,
+                                      const struct per_var_ws *pvw,
+                                      const struct descriptive_data *dd_i, const struct descriptive_data *dd_j,
+                                      const struct posthoc *ph)
+{
+  int k = pvw->n_groups;
+  double df = ph->dff (pvw, dd_i->mom, dd_j->mom);
+  double ts = ph->tsf (k, dd_i->mom, dd_j->mom, std_err);
+  return  ph->p1f (ts, k - 1, df);
+}
+
+static double 
+mc_half_range (const struct oneway_spec *cmd, const struct per_var_ws *pvw, double std_err, const struct descriptive_data *dd_i, const struct descriptive_data *dd_j, const struct posthoc *ph)
+{
+  int k = pvw->n_groups;
+  double df = ph->dff (pvw, dd_i->mom, dd_j->mom);
+
+  return ph->pinv (std_err, cmd->alpha, df, k, dd_i->mom, dd_j->mom);
+}
+
+static double tukey_1tailsig (double ts, double df1, double df2)
+{
+  double twotailedsig = 1.0 - ptukey (ts, 1.0, df1 + 1, df2, 1, 0);
+
+  return twotailedsig / 2.0;
+}
+
+static double lsd_1tailsig (double ts, double df1 UNUSED, double df2)
+{
+  return ts < 0 ? gsl_cdf_tdist_P (ts, df2) : gsl_cdf_tdist_Q (ts, df2);
+}
+
+static double sidak_1tailsig (double ts, double df1, double df2)
+{
+  double ex = (df1 + 1.0) * df1 / 2.0;
+  double lsd_sig = 2 * lsd_1tailsig (ts, df1, df2);
+
+  return 0.5 * (1.0 - pow (1.0 - lsd_sig, ex));
+}
+
+static double bonferroni_1tailsig (double ts, double df1, double df2)
+{
+  const int m = (df1 + 1) * df1 / 2;
+
+  double p = ts < 0 ? gsl_cdf_tdist_P (ts, df2) : gsl_cdf_tdist_Q (ts, df2);
+  p *= m;
+
+  return p > 0.5 ? 0.5 : p;
+}
+
+static double scheffe_1tailsig (double ts, double df1, double df2)
+{
+  return 0.5 * gsl_cdf_fdist_Q (ts, df1, df2);
+}
+
+
+static double tukey_test_stat (int k UNUSED, const struct moments1 *mom_i, const struct moments1 *mom_j, double std_err)
+{
+  double ts;
+  double n_i, mean_i, var_i;
+  double n_j, mean_j, var_j;
+
+  moments1_calculate (mom_i, &n_i, &mean_i, &var_i, 0, 0);  
+  moments1_calculate (mom_j, &n_j, &mean_j, &var_j, 0, 0);
+
+  ts =  (mean_i - mean_j) / std_err;
+  ts = fabs (ts) * sqrt (2.0);
+
+  return ts;
+}
+
+static double lsd_test_stat (int k UNUSED, const struct moments1 *mom_i, const struct moments1 *mom_j, double std_err)
+{
+  double n_i, mean_i, var_i;
+  double n_j, mean_j, var_j;
+
+  moments1_calculate (mom_i, &n_i, &mean_i, &var_i, 0, 0);  
+  moments1_calculate (mom_j, &n_j, &mean_j, &var_j, 0, 0);
+
+  return (mean_i - mean_j) / std_err;
+}
+
+static double scheffe_test_stat (int k, const struct moments1 *mom_i, const struct moments1 *mom_j, double std_err)
+{
+  double t;
+  double n_i, mean_i, var_i;
+  double n_j, mean_j, var_j;
+
+  moments1_calculate (mom_i, &n_i, &mean_i, &var_i, 0, 0);  
+  moments1_calculate (mom_j, &n_j, &mean_j, &var_j, 0, 0);
+
+  t = (mean_i - mean_j) / std_err;
+  t = pow2 (t);
+  t /= k - 1;
+
+  return t;
+}
+
+static double gh_test_stat (int k UNUSED, const struct moments1 *mom_i, const struct moments1 *mom_j, double std_err UNUSED)
+{
+  double ts;
+  double thing;
+  double n_i, mean_i, var_i;
+  double n_j, mean_j, var_j;
+
+  moments1_calculate (mom_i, &n_i, &mean_i, &var_i, 0, 0);  
+  moments1_calculate (mom_j, &n_j, &mean_j, &var_j, 0, 0);
+
+  thing = var_i / n_i + var_j / n_j;
+  thing /= 2.0;
+  thing = sqrt (thing);
+
+  ts = (mean_i - mean_j) / thing;
+
+  return fabs (ts);
+}
+
+
+
+static const struct posthoc ph_tests [] = 
+  {
+    { "LSD",        N_("LSD"),          df_common, lsd_test_stat,     lsd_1tailsig,          lsd_pinv},
+    { "TUKEY",      N_("Tukey HSD"),    df_common, tukey_test_stat,   tukey_1tailsig,        tukey_pinv},
+    { "BONFERRONI", N_("Bonferroni"),   df_common, lsd_test_stat,     bonferroni_1tailsig,   bonferroni_pinv},
+    { "SCHEFFE",    N_("Scheffé"),      df_common, scheffe_test_stat, scheffe_1tailsig,      scheffe_pinv},
+    { "GH",         N_("Games-Howell"), df_individual, gh_test_stat,  tukey_1tailsig,        gh_pinv},
+    { "SIDAK",      N_("Šidák"),        df_common, lsd_test_stat,     sidak_1tailsig,        sidak_pinv}
+  };
 
-  double mse;
-  double levene_w;
-};
 
 struct oneway_workspace
 {
@@ -152,6 +378,9 @@ cmd_oneway (struct lexer *lexer, struct dataset *ds)
   oneway.missing_type = MISS_ANALYSIS;
   oneway.exclude = MV_ANY;
   oneway.wv = dict_get_weight (dict);
+  oneway.alpha = 0.05;
+  oneway.posthoc = NULL;
+  oneway.n_posthoc = 0;
 
   ll_init (&oneway.contrast_list);
 
@@ -198,6 +427,45 @@ cmd_oneway (struct lexer *lexer, struct dataset *ds)
                }
            }
        }
+      else if (lex_match_id (lexer, "POSTHOC"))
+       {
+          lex_match (lexer, T_EQUALS);
+          while (lex_token (lexer) != T_ENDCMD && lex_token (lexer) != T_SLASH)
+           {
+             int p;
+             bool method = false;
+             for (p = 0 ; p < sizeof (ph_tests) / sizeof (struct posthoc); ++p)
+               {
+                 if (lex_match_id (lexer, ph_tests[p].syntax))
+                   {
+                     oneway.n_posthoc++;
+                     oneway.posthoc = xrealloc (oneway.posthoc, sizeof (*oneway.posthoc) * oneway.n_posthoc);
+                     oneway.posthoc[oneway.n_posthoc - 1] = p;
+                     method = true;
+                     break;
+                   }
+               }
+             if ( method == false)
+               {
+                 if (lex_match_id (lexer, "ALPHA"))
+                   {
+                     if ( !lex_force_match (lexer, T_LPAREN))
+                       goto error;
+                     lex_force_num (lexer);
+                     oneway.alpha = lex_number (lexer);
+                     lex_get (lexer);
+                     if ( !lex_force_match (lexer, T_RPAREN))
+                       goto error;
+                   }
+                 else
+                   {
+                     msg (SE, _("The post hoc analysis method %s is not supported."), lex_tokcstr (lexer));
+                     lex_error (lexer, NULL);
+                     goto error;
+                   }
+               }
+           }
+       }
       else if (lex_match_id (lexer, "CONTRAST"))
        {
          struct contrasts_node *cl = xzalloc (sizeof *cl);
@@ -384,15 +652,16 @@ run_oneway (const struct oneway_spec *cmd,
 
   for (v = 0; v < cmd->n_vars; ++v)
     {
-      ws.vws[v].cat = categoricals_create (&cmd->indep_var, 1, cmd->wv,
+      struct interaction *inter = interaction_create (cmd->indep_var);
+      ws.vws[v].cat = categoricals_create (&inter, 1, cmd->wv,
                                            cmd->exclude, makeit, updateit,
-                                           CONST_CAST (struct variable *,
-                                                       cmd->vars[v]),
+                                           CONST_CAST (struct variable *, cmd->vars[v]),
                                            ws.dd_total[v]);
 
       ws.vws[v].cov = covariance_2pass_create (1, &cmd->vars[v],
                                               ws.vws[v].cat, 
                                               cmd->wv, cmd->exclude);
+      ws.vws[v].nl = levene_create (var_get_width (cmd->indep_var), NULL);
     }
 
   c = casereader_peek (input, 0);
@@ -413,20 +682,11 @@ run_oneway (const struct oneway_spec *cmd,
                                               cmd->exclude, NULL, NULL);
   input = casereader_create_filter_weight (input, dict, NULL, NULL);
 
-
-  if (cmd->stats & STATS_HOMOGENEITY)
-    for (v = 0; v < cmd->n_vars; ++v)
-      {
-       struct per_var_ws *pvw = &ws.vws[v];
-
-       pvw->levene_w = levene (input, cmd->indep_var, cmd->vars[v], cmd->wv, cmd->exclude);
-      }
-
   reader = casereader_clone (input);
-
   for (; (c = casereader_read (reader)) != NULL; case_unref (c))
     {
       int i;
+      double w = dict_get_case_weight (dict, c, NULL);
 
       for (i = 0; i < cmd->n_vars; ++i)
        {
@@ -441,13 +701,16 @@ run_oneway (const struct oneway_spec *cmd,
            }
 
          covariance_accumulate_pass1 (pvw->cov, c);
+         levene_pass_one (pvw->nl, val->f, w, case_data (c, cmd->indep_var));
        }
     }
   casereader_destroy (reader);
+
   reader = casereader_clone (input);
   for ( ; (c = casereader_read (reader) ); case_unref (c))
     {
       int i;
+      double w = dict_get_case_weight (dict, c, NULL);
       for (i = 0; i < cmd->n_vars; ++i)
        {
          struct per_var_ws *pvw = &ws.vws[i];
@@ -461,22 +724,46 @@ run_oneway (const struct oneway_spec *cmd,
            }
 
          covariance_accumulate_pass2 (pvw->cov, c);
+         levene_pass_two (pvw->nl, val->f, w, case_data (c, cmd->indep_var));
+       }
+    }
+  casereader_destroy (reader);
+
+  reader = casereader_clone (input);
+  for ( ; (c = casereader_read (reader) ); case_unref (c))
+    {
+      int i;
+      double w = dict_get_case_weight (dict, c, NULL);
+
+      for (i = 0; i < cmd->n_vars; ++i)
+       {
+         struct per_var_ws *pvw = &ws.vws[i];
+         const struct variable *v = cmd->vars[i];
+         const union value *val = case_data (c, v);
+
+         if ( MISS_ANALYSIS == cmd->missing_type)
+           {
+             if ( var_is_value_missing (v, val, cmd->exclude))
+               continue;
+           }
+
+         levene_pass_three (pvw->nl, val->f, w, case_data (c, cmd->indep_var));
        }
     }
   casereader_destroy (reader);
 
+
   for (v = 0; v < cmd->n_vars; ++v)
     {
       struct per_var_ws *pvw = &ws.vws[v];
-      gsl_matrix *cm = covariance_calculate_unnormalized (pvw->cov);
       const struct categoricals *cats = covariance_get_categoricals (pvw->cov);
+      categoricals_done (cats);
 
-      double n;
-      moments1_calculate (ws.dd_total[v]->mom, &n, NULL, NULL, NULL, NULL);
+      gsl_matrix *cm = covariance_calculate_unnormalized (pvw->cov);
 
-      pvw->sst = gsl_matrix_get (cm, 0, 0);
+      moments1_calculate (ws.dd_total[v]->mom, &pvw->n, NULL, NULL, NULL, NULL);
 
-      //      gsl_matrix_fprintf (stdout, cm, "%g ");
+      pvw->sst = gsl_matrix_get (cm, 0, 0);
 
       reg_sweep (cm, 0);
 
@@ -484,9 +771,9 @@ run_oneway (const struct oneway_spec *cmd,
 
       pvw->ssa = pvw->sst - pvw->sse;
 
-      pvw->n_groups = categoricals_total (cats);
+      pvw->n_groups = categoricals_n_total (cats);
 
-      pvw->mse = (pvw->sst - pvw->ssa) / (n - pvw->n_groups);
+      pvw->mse = (pvw->sst - pvw->ssa) / (pvw->n - pvw->n_groups);
 
       gsl_matrix_free (cm);
     }
@@ -495,10 +782,8 @@ run_oneway (const struct oneway_spec *cmd,
     {
       const struct categoricals *cats = covariance_get_categoricals (ws.vws[v].cov);
 
-      categoricals_done (cats);
-      
-      if (categoricals_total (cats) > ws.actual_number_of_groups)
-       ws.actual_number_of_groups = categoricals_total (cats);
+      if (categoricals_n_total (cats) > ws.actual_number_of_groups)
+       ws.actual_number_of_groups = categoricals_n_total (cats);
     }
 
   casereader_destroy (input);
@@ -512,15 +797,16 @@ run_oneway (const struct oneway_spec *cmd,
   for (v = 0; v < cmd->n_vars; ++v)
     {
       covariance_destroy (ws.vws[v].cov);
+      levene_destroy (ws.vws[v].nl);
       dd_destroy (ws.dd_total[v]);
     }
   free (ws.vws);
   free (ws.dd_total);
-
 }
 
 static void show_contrast_coeffs (const struct oneway_spec *cmd, const struct oneway_workspace *ws);
 static void show_contrast_tests (const struct oneway_spec *cmd, const struct oneway_workspace *ws);
+static void show_comparisons (const struct oneway_spec *cmd, const struct oneway_workspace *ws, int depvar);
 
 static void
 output_oneway (const struct oneway_spec *cmd, struct oneway_workspace *ws)
@@ -529,7 +815,8 @@ output_oneway (const struct oneway_spec *cmd, struct oneway_workspace *ws)
 
   /* Check the sanity of the given contrast values */
   struct contrasts_node *coeff_list  = NULL;
-  ll_for_each (coeff_list, struct contrasts_node, ll, &cmd->contrast_list)
+  struct contrasts_node *coeff_next  = NULL;
+  ll_for_each_safe (coeff_list, coeff_next, struct contrasts_node, ll, &cmd->contrast_list)
     {
       struct coeff_node *cn = NULL;
       double sum = 0;
@@ -539,8 +826,10 @@ output_oneway (const struct oneway_spec *cmd, struct oneway_workspace *ws)
       if (ll_count (cl) != ws->actual_number_of_groups)
        {
          msg (SW,
-              _("Number of contrast coefficients must equal the number of groups"));
-         coeff_list->bad_count = true;
+              _("In contrast list %zu, the number of coefficients (%d) does not equal the number of groups (%d). This contrast list will be ignored."),
+              i, ll_count (cl), ws->actual_number_of_groups);
+
+         ll_remove (&coeff_list->ll);
          continue;
        }
 
@@ -564,6 +853,13 @@ output_oneway (const struct oneway_spec *cmd, struct oneway_workspace *ws)
       show_contrast_coeffs (cmd, ws);
       show_contrast_tests (cmd, ws);
     }
+
+  if ( cmd->posthoc )
+    {
+      int v;
+      for (v = 0 ; v < cmd->n_vars; ++v)
+       show_comparisons (cmd, ws, v);
+    }
 }
 
 
@@ -718,7 +1014,7 @@ show_descriptives (const struct oneway_spec *cmd, const struct oneway_workspace
       if ( v > 0)
        tab_hline (t, TAL_1, 0, n_cols - 1, row);
 
-      for (count = 0; count < categoricals_total (cats); ++count)
+      for (count = 0; count < categoricals_n_total (cats); ++count)
        {
          double T;
          double n, mean, variance;
@@ -726,8 +1022,8 @@ show_descriptives (const struct oneway_spec *cmd, const struct oneway_workspace
 
          struct string vstr;
 
-         const union value *gval = categoricals_get_value_by_subscript (cats, count);
-         const struct descriptive_data *dd = categoricals_get_user_data_by_subscript (cats, count);
+         const struct ccase *gcc = categoricals_get_case_by_category (cats, count);
+         const struct descriptive_data *dd = categoricals_get_user_data_by_category (cats, count);
 
          moments1_calculate (dd->mom, &n, &mean, &variance, NULL, NULL);
 
@@ -736,7 +1032,7 @@ show_descriptives (const struct oneway_spec *cmd, const struct oneway_workspace
 
          ds_init_empty (&vstr);
 
-         var_append_value_name (cmd->indep_var, gval, &vstr);
+         var_append_value_name (cmd->indep_var, case_data (gcc, cmd->indep_var), &vstr);
 
          tab_text (t, 1, row + count,
                    TAB_LEFT | TAT_TITLE,
@@ -807,7 +1103,7 @@ show_descriptives (const struct oneway_spec *cmd, const struct oneway_workspace
        tab_double (t, 9, row + count, 0,  ws->dd_total[v]->maximum, fmt);
       }
 
-      row += categoricals_total (cats) + 1;
+      row += categoricals_n_total (cats) + 1;
     }
 
   tab_submit (t);
@@ -846,7 +1142,7 @@ show_homogeneity (const struct oneway_spec *cmd, const struct oneway_workspace *
     {
       double n;
       const struct per_var_ws *pvw = &ws->vws[v];
-      double F = pvw->levene_w;
+      double F = levene_calculate (pvw->nl);
 
       const struct variable *var = cmd->vars[v];
       const char *s = var_to_string (var);
@@ -936,25 +1232,19 @@ show_contrast_coeffs (const struct oneway_spec *cmd, const struct oneway_workspa
           ++count, coeffi = ll_next (coeffi))
        {
          const struct categoricals *cats = covariance_get_categoricals (cov);
-         const union value *val = categoricals_get_value_by_subscript (cats, count);
+         const struct ccase *gcc = categoricals_get_case_by_category (cats, count);
+         struct coeff_node *coeffn = ll_data (coeffi, struct coeff_node, ll);
          struct string vstr;
 
          ds_init_empty (&vstr);
 
-         var_append_value_name (cmd->indep_var, val, &vstr);
+         var_append_value_name (cmd->indep_var, case_data (gcc, cmd->indep_var), &vstr);
 
          tab_text (t, count + 2, 1, TAB_CENTER | TAT_TITLE, ds_cstr (&vstr));
 
          ds_destroy (&vstr);
 
-         if (cn->bad_count)
-           tab_text (t, count + 2, c_num + 2, TAB_RIGHT, "?" );
-         else
-           {
-             struct coeff_node *coeffn = ll_data (coeffi, struct coeff_node, ll);
-
-             tab_text_format (t, count + 2, c_num + 2, TAB_RIGHT, "%g", coeffn->coeff);
-           }
+         tab_text_format (t, count + 2, c_num + 2, TAB_RIGHT, "%g", coeffn->coeff);
        }
       ++c_num;
     }
@@ -1065,15 +1355,12 @@ show_contrast_tests (const struct oneway_spec *cmd, const struct oneway_workspac
                            (v * lines_per_variable) + i + 1 + n_contrasts,
                            TAB_CENTER | TAT_TITLE, "%d", i + 1);
 
-         if (cn->bad_count)
-           continue;
-
          for (coeffi = ll_head (&cn->coefficient_list);
               coeffi != ll_null (&cn->coefficient_list);
               ++ci, coeffi = ll_next (coeffi))
            {
              double n, mean, variance;
-             const struct descriptive_data *dd = categoricals_get_user_data_by_subscript (cats, ci);
+             const struct descriptive_data *dd = categoricals_get_user_data_by_category (cats, ci);
              struct coeff_node *cn = ll_data (coeffi, struct coeff_node, ll);
              const double coef = cn->coeff; 
              double winv ;
@@ -1165,3 +1452,127 @@ show_contrast_tests (const struct oneway_spec *cmd, const struct oneway_workspac
 }
 
 
+
+static void
+show_comparisons (const struct oneway_spec *cmd, const struct oneway_workspace *ws, int v)
+{
+  const int n_cols = 8;
+  const int heading_rows = 2;
+  const int heading_cols = 3;
+
+  int p;
+  int r = heading_rows ;
+
+  const struct per_var_ws *pvw = &ws->vws[v];
+  const struct categoricals *cat = pvw->cat;
+  const int n_rows = heading_rows + cmd->n_posthoc * pvw->n_groups * (pvw->n_groups - 1);
+
+  struct tab_table *t = tab_create (n_cols, n_rows);
+
+  tab_headers (t, heading_cols, 0, heading_rows, 0);
+
+  /* Put a frame around the entire box, and vertical lines inside */
+  tab_box (t,
+          TAL_2, TAL_2,
+          -1, -1,
+          0, 0,
+          n_cols - 1, n_rows - 1);
+
+  tab_box (t,
+          -1, -1,
+          -1, TAL_1,
+          heading_cols, 0,
+          n_cols - 1, n_rows - 1);
+
+  tab_vline (t, TAL_2, heading_cols, 0, n_rows - 1);
+
+  tab_title (t, _("Multiple Comparisons"));
+
+  tab_text_format (t,  1, 1, TAB_LEFT | TAT_TITLE, _("(I) %s"), var_to_string (cmd->indep_var));
+  tab_text_format (t,  2, 1, TAB_LEFT | TAT_TITLE, _("(J) %s"), var_to_string (cmd->indep_var));
+  tab_text (t,  3, 0, TAB_CENTER | TAT_TITLE, _("Mean Difference"));
+  tab_text (t,  3, 1, TAB_CENTER | TAT_TITLE, _("(I - J)"));
+  tab_text (t,  4, 1, TAB_CENTER | TAT_TITLE, _("Std. Error"));
+  tab_text (t,  5, 1, TAB_CENTER | TAT_TITLE, _("Sig."));
+
+  tab_joint_text_format (t, 6, 0, 7, 0, TAB_CENTER | TAT_TITLE,
+                         _("%g%% Confidence Interval"),
+                         (1 - cmd->alpha) * 100.0);
+
+  tab_text (t,  6, 1, TAB_CENTER | TAT_TITLE, _("Lower Bound"));
+  tab_text (t,  7, 1, TAB_CENTER | TAT_TITLE, _("Upper Bound"));
+
+
+  for (p = 0; p < cmd->n_posthoc; ++p)
+    {
+      int i;
+      const struct posthoc *ph = &ph_tests[cmd->posthoc[p]];
+
+      tab_hline (t, TAL_2, 0, n_cols - 1, r);
+
+      tab_text (t, 0, r, TAB_LEFT | TAT_TITLE, gettext (ph->label));
+
+      for (i = 0; i < pvw->n_groups ; ++i)
+       {
+         double weight_i, mean_i, var_i;
+         int rx = 0;
+         struct string vstr;
+         int j;
+         struct descriptive_data *dd_i = categoricals_get_user_data_by_category (cat, i);
+         const struct ccase *gcc = categoricals_get_case_by_category (cat, i);
+         
+
+         ds_init_empty (&vstr);
+         var_append_value_name (cmd->indep_var, case_data (gcc, cmd->indep_var), &vstr);
+
+         if ( i != 0)
+           tab_hline (t, TAL_1, 1, n_cols - 1, r);
+         tab_text (t, 1, r, TAB_LEFT | TAT_TITLE, ds_cstr (&vstr));
+
+         moments1_calculate (dd_i->mom, &weight_i, &mean_i, &var_i, 0, 0);
+
+         for (j = 0 ; j < pvw->n_groups; ++j)
+           {
+             double std_err;
+             double weight_j, mean_j, var_j;
+             double half_range;
+             const struct ccase *cc;
+             struct descriptive_data *dd_j = categoricals_get_user_data_by_category (cat, j);
+             if (j == i)
+               continue;
+
+             ds_clear (&vstr);
+             cc = categoricals_get_case_by_category (cat, j);
+             var_append_value_name (cmd->indep_var, case_data (cc, cmd->indep_var), &vstr);
+             tab_text (t, 2, r + rx, TAB_LEFT | TAT_TITLE, ds_cstr (&vstr));
+
+             moments1_calculate (dd_j->mom, &weight_j, &mean_j, &var_j, 0, 0);
+
+             tab_double  (t, 3, r + rx, 0, mean_i - mean_j, 0);
+
+             std_err = pvw->mse;
+             std_err *= weight_i + weight_j;
+             std_err /= weight_i * weight_j;
+             std_err = sqrt (std_err);
+
+             tab_double  (t, 4, r + rx, 0, std_err, 0);
+         
+             tab_double (t, 5, r + rx, 0, 2 * multiple_comparison_sig (std_err, pvw, dd_i, dd_j, ph), 0);
+
+             half_range = mc_half_range (cmd, pvw, std_err, dd_i, dd_j, ph);
+
+             tab_double (t, 6, r + rx, 0,
+                          (mean_i - mean_j) - half_range, 0 );
+
+             tab_double (t, 7, r + rx, 0,
+                          (mean_i - mean_j) + half_range, 0 );
+
+             rx++;
+           }
+         ds_destroy (&vstr);
+         r += pvw->n_groups - 1;
+       }
+    }
+
+  tab_submit (t);
+}
index 014406f098aa53adf20ef12136e30d800b751cdb..e6987f4b10b5db503a799b66665a796665407a17 100644 (file)
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
 
+enum missing_type
+  {
+    MISS_LISTWISE,
+    MISS_PAIRWISE,
+  };
+
+
+struct qc
+{
+  const struct variable **vars;
+  size_t n_vars;
+
+  int ngroups;                 /* Number of group. (Given by the user) */
+  int maxiter;                 /* Maximum iterations (Given by the user) */
+
+  const struct variable *wv;   /* Weighting variable. */
+
+  enum missing_type missing_type;
+  enum mv_class exclude;
+};
+
 /* Holds all of the information for the functions.  int n, holds the number of
    observation and its default value is -1.  We set it in
    kmeans_recalculate_centers in first invocation. */
@@ -53,44 +74,39 @@ struct Kmeans
 {
   gsl_matrix *centers;         /* Centers for groups. */
   gsl_vector_long *num_elements_groups;
-  int ngroups;                 /* Number of group. (Given by the user) */
+
   casenumber n;                        /* Number of observations (default -1). */
-  int m;                       /* Number of variables. (Given by the user) */
-  int maxiter;                 /* Maximum iterations (Given by the user) */
+
   int lastiter;                        /* Iteration where it found the solution. */
   int trials;                  /* If not convergence, how many times has
                                    clustering done. */
   gsl_matrix *initial_centers; /* Initial random centers. */
-  const struct variable **variables;
+
   gsl_permutation *group_order;        /* Group order for reporting. */
-  struct casereader *original_casereader;
   struct caseproto *proto;
   struct casereader *index_rdr;        /* Group ids for each case. */
-  const struct variable *wv;   /* Weighting variable. */
 };
 
-static struct Kmeans *kmeans_create (struct casereader *cs,
-                                    const struct variable **variables,
-                                    int m, int ngroups, int maxiter);
+static struct Kmeans *kmeans_create (const struct qc *qc);
 
-static void kmeans_randomize_centers (struct Kmeans *kmeans);
+static void kmeans_randomize_centers (struct Kmeans *kmeans, const struct qc *qc);
 
-static int kmeans_get_nearest_group (struct Kmeans *kmeans, struct ccase *c);
+static int kmeans_get_nearest_group (struct Kmeans *kmeans, struct ccase *c, const struct qc *);
 
-static void kmeans_recalculate_centers (struct Kmeans *kmeans);
+static void kmeans_recalculate_centers (struct Kmeans *kmeans, const struct casereader *reader, const struct qc *);
 
 static int
-kmeans_calculate_indexes_and_check_convergence (struct Kmeans *kmeans);
+kmeans_calculate_indexes_and_check_convergence (struct Kmeans *kmeans, const struct casereader *reader, const struct qc *);
 
-static void kmeans_order_groups (struct Kmeans *kmeans);
+static void kmeans_order_groups (struct Kmeans *kmeans, const struct qc *);
 
-static void kmeans_cluster (struct Kmeans *kmeans);
+static void kmeans_cluster (struct Kmeans *kmeans, struct casereader *reader, const struct qc *);
 
-static void quick_cluster_show_centers (struct Kmeans *kmeans, bool initial);
+static void quick_cluster_show_centers (struct Kmeans *kmeans, bool initial, const struct qc *);
 
-static void quick_cluster_show_number_cases (struct Kmeans *kmeans);
+static void quick_cluster_show_number_cases (struct Kmeans *kmeans, const struct qc *);
 
-static void quick_cluster_show_results (struct Kmeans *kmeans);
+static void quick_cluster_show_results (struct Kmeans *kmeans, const struct qc *);
 
 int cmd_quick_cluster (struct lexer *lexer, struct dataset *ds);
 
@@ -100,21 +116,15 @@ static void kmeans_destroy (struct Kmeans *kmeans);
    variables 'variables', number of cases 'n', number of variables 'm', number
    of clusters and amount of maximum iterations. */
 static struct Kmeans *
-kmeans_create (struct casereader *cs, const struct variable **variables,
-              int m, int ngroups, int maxiter)
+kmeans_create (const struct qc *qc)
 {
   struct Kmeans *kmeans = xmalloc (sizeof (struct Kmeans));
-  kmeans->centers = gsl_matrix_alloc (ngroups, m);
-  kmeans->num_elements_groups = gsl_vector_long_alloc (ngroups);
-  kmeans->ngroups = ngroups;
+  kmeans->centers = gsl_matrix_alloc (qc->ngroups, qc->n_vars);
+  kmeans->num_elements_groups = gsl_vector_long_alloc (qc->ngroups);
   kmeans->n = 0;
-  kmeans->m = m;
-  kmeans->maxiter = maxiter;
   kmeans->lastiter = 0;
   kmeans->trials = 0;
-  kmeans->variables = variables;
   kmeans->group_order = gsl_permutation_alloc (kmeans->centers->size1);
-  kmeans->original_casereader = cs;
   kmeans->initial_centers = NULL;
 
   kmeans->proto = caseproto_create ();
@@ -135,23 +145,19 @@ kmeans_destroy (struct Kmeans *kmeans)
 
   caseproto_unref (kmeans->proto);
 
-  /*
-     These reader and writer were already destroyed.
-     free (kmeans->original_casereader);
-     free (kmeans->index_rdr);
-   */
+  casereader_destroy (kmeans->index_rdr);
 
   free (kmeans);
 }
 
 /* Creates random centers using randomly selected cases from the data. */
 static void
-kmeans_randomize_centers (struct Kmeans *kmeans)
+kmeans_randomize_centers (struct Kmeans *kmeans, const struct qc *qc)
 {
   int i, j;
-  for (i = 0; i < kmeans->ngroups; i++)
+  for (i = 0; i < qc->ngroups; i++)
     {
-      for (j = 0; j < kmeans->m; j++)
+      for (j = 0; j < qc->n_vars; j++)
        {
          if (i == j)
            {
@@ -169,27 +175,27 @@ kmeans_randomize_centers (struct Kmeans *kmeans)
      here. */
   if (!kmeans->initial_centers)
     {
-      kmeans->initial_centers = gsl_matrix_alloc (kmeans->ngroups, kmeans->m);
+      kmeans->initial_centers = gsl_matrix_alloc (qc->ngroups, qc->n_vars);
       gsl_matrix_memcpy (kmeans->initial_centers, kmeans->centers);
     }
 }
 
 static int
-kmeans_get_nearest_group (struct Kmeans *kmeans, struct ccase *c)
+kmeans_get_nearest_group (struct Kmeans *kmeans, struct ccase *c, const struct qc *qc)
 {
   int result = -1;
-  double x;
   int i, j;
-  double dist;
-  double mindist;
-  mindist = INFINITY;
-  for (i = 0; i < kmeans->ngroups; i++)
+  double mindist = INFINITY;
+  for (i = 0; i < qc->ngroups; i++)
     {
-      dist = 0;
-      for (j = 0; j < kmeans->m; j++)
+      double dist = 0;
+      for (j = 0; j < qc->n_vars; j++)
        {
-         x = case_data (c, kmeans->variables[j])->f;
-         dist += pow2 (gsl_matrix_get (kmeans->centers, i, j) - x);
+         const union value *val = case_data (c, qc->vars[j]);
+         if ( var_is_value_missing (qc->vars[j], val, qc->exclude))
+           continue;
+
+         dist += pow2 (gsl_matrix_get (kmeans->centers, i, j) - val->f);
        }
       if (dist < mindist)
        {
@@ -202,38 +208,30 @@ kmeans_get_nearest_group (struct Kmeans *kmeans, struct ccase *c)
 
 /* Re-calculate the cluster centers. */
 static void
-kmeans_recalculate_centers (struct Kmeans *kmeans)
+kmeans_recalculate_centers (struct Kmeans *kmeans, const struct casereader *reader, const struct qc *qc)
 {
-  casenumber i;
+  casenumber i = 0;
   int v, j;
-  double x, curval;
   struct ccase *c;
-  struct ccase *c_index;
-  struct casereader *cs;
-  struct casereader *cs_index;
-  int index;
-  double weight;
 
-  i = 0;
-  cs = casereader_clone (kmeans->original_casereader);
-  cs_index = casereader_clone (kmeans->index_rdr);
+  struct casereader *cs = casereader_clone (reader);
+  struct casereader *cs_index = casereader_clone (kmeans->index_rdr);
 
   gsl_matrix_set_all (kmeans->centers, 0.0);
   for (; (c = casereader_read (cs)) != NULL; case_unref (c))
     {
-      c_index = casereader_read (cs_index);
-      index = case_data_idx (c_index, 0)->f;
-      for (v = 0; v < kmeans->m; ++v)
+      double weight = qc->wv ? case_data (c, qc->wv)->f : 1.0;
+      struct ccase *c_index = casereader_read (cs_index);
+      int index = case_data_idx (c_index, 0)->f;
+      for (v = 0; v < qc->n_vars; ++v)
        {
-         if (kmeans->wv)
-           {
-             weight = case_data (c, kmeans->wv)->f;
-           }
-         else
-           {
-             weight = 1.0;
-           }
-         x = case_data (c, kmeans->variables[v])->f * weight;
+         const union value *val = case_data (c, qc->vars[v]);
+         double x = val->f * weight;
+         double curval;
+
+         if ( var_is_value_missing (qc->vars[v], val, qc->exclude))
+           continue;
+
          curval = gsl_matrix_get (kmeans->centers, index, v);
          gsl_matrix_set (kmeans->centers, index, v, curval + x);
        }
@@ -250,10 +248,10 @@ kmeans_recalculate_centers (struct Kmeans *kmeans)
   /* We got sum of each center but we need averages.
      We are dividing centers to numobs. This may be inefficient and
      we should check it again. */
-  for (i = 0; i < kmeans->ngroups; i++)
+  for (i = 0; i < qc->ngroups; i++)
     {
       casenumber numobs = kmeans->num_elements_groups->data[i];
-      for (j = 0; j < kmeans->m; j++)
+      for (j = 0; j < qc->n_vars; j++)
        {
          if (numobs > 0)
            {
@@ -274,12 +272,11 @@ kmeans_recalculate_centers (struct Kmeans *kmeans)
    different cases of the new and old index variables.  If last two index
    variables are equal, there is no any enhancement of clustering. */
 static int
-kmeans_calculate_indexes_and_check_convergence (struct Kmeans *kmeans)
+kmeans_calculate_indexes_and_check_convergence (struct Kmeans *kmeans, const struct casereader *reader, const struct qc *qc)
 {
   int totaldiff = 0;
-  double weight;
   struct ccase *c;
-  struct casereader *cs = casereader_clone (kmeans->original_casereader);
+  struct casereader *cs = casereader_clone (reader);
 
   /* A casewriter into which we will write the indexes. */
   struct casewriter *index_wtr = autopaging_writer_create (kmeans->proto);
@@ -290,15 +287,9 @@ kmeans_calculate_indexes_and_check_convergence (struct Kmeans *kmeans)
     {
       /* A case to hold the new index. */
       struct ccase *index_case_new = case_create (kmeans->proto);
-      int bestindex = kmeans_get_nearest_group (kmeans, c);
-      if (kmeans->wv)
-       {
-         weight = (casenumber) case_data (c, kmeans->wv)->f;
-       }
-      else
-       {
-         weight = 1.0;
-       }
+      int bestindex = kmeans_get_nearest_group (kmeans, c, qc);
+      double weight = qc->wv ? case_data (c, qc->wv)->f : 1.0;
+      assert (bestindex < kmeans->num_elements_groups->size);
       kmeans->num_elements_groups->data[bestindex] += weight;
       if (kmeans->index_rdr)
        {
@@ -338,17 +329,18 @@ kmeans_calculate_indexes_and_check_convergence (struct Kmeans *kmeans)
 }
 
 static void
-kmeans_order_groups (struct Kmeans *kmeans)
+kmeans_order_groups (struct Kmeans *kmeans, const struct qc *qc)
 {
-  gsl_vector *v = gsl_vector_alloc (kmeans->ngroups);
+  gsl_vector *v = gsl_vector_alloc (qc->ngroups);
   gsl_matrix_get_col (v, kmeans->centers, 0);
   gsl_sort_vector_index (kmeans->group_order, v);
+  gsl_vector_free (v);
 }
 
 /* Main algorithm.
    Does iterations, checks convergency. */
 static void
-kmeans_cluster (struct Kmeans *kmeans)
+kmeans_cluster (struct Kmeans *kmeans, struct casereader *reader, const struct qc *qc)
 {
   int i;
   bool redo;
@@ -358,13 +350,13 @@ kmeans_cluster (struct Kmeans *kmeans)
   show_warning1 = true;
 cluster:
   redo = false;
-  kmeans_randomize_centers (kmeans);
-  for (kmeans->lastiter = 0; kmeans->lastiter < kmeans->maxiter;
+  kmeans_randomize_centers (kmeans, qc);
+  for (kmeans->lastiter = 0; kmeans->lastiter < qc->maxiter;
        kmeans->lastiter++)
     {
-      diffs = kmeans_calculate_indexes_and_check_convergence (kmeans);
-      kmeans_recalculate_centers (kmeans);
-      if (show_warning1 && kmeans->ngroups > kmeans->n)
+      diffs = kmeans_calculate_indexes_and_check_convergence (kmeans, reader, qc);
+      kmeans_recalculate_centers (kmeans, reader, qc);
+      if (show_warning1 && qc->ngroups > kmeans->n)
        {
          msg (MW, _("Number of clusters may not be larger than the number "
                      "of cases."));
@@ -374,7 +366,7 @@ cluster:
        break;
     }
 
-  for (i = 0; i < kmeans->ngroups; i++)
+  for (i = 0; i < qc->ngroups; i++)
     {
       if (kmeans->num_elements_groups->data[i] == 0)
        {
@@ -395,13 +387,13 @@ cluster:
    If initial is true, initial cluster centers are reported.  Otherwise,
    resulted centers are reported. */
 static void
-quick_cluster_show_centers (struct Kmeans *kmeans, bool initial)
+quick_cluster_show_centers (struct Kmeans *kmeans, bool initial, const struct qc *qc)
 {
   struct tab_table *t;
   int nc, nr, heading_columns, currow;
   int i, j;
-  nc = kmeans->ngroups + 1;
-  nr = kmeans->m + 4;
+  nc = qc->ngroups + 1;
+  nr = qc->n_vars + 4;
   heading_columns = 1;
   t = tab_create (nc, nr);
   tab_headers (t, 0, nc - 1, 0, 1);
@@ -419,36 +411,36 @@ quick_cluster_show_centers (struct Kmeans *kmeans, bool initial)
   tab_hline (t, TAL_1, 1, nc - 1, 2);
   currow += 2;
 
-  for (i = 0; i < kmeans->ngroups; i++)
+  for (i = 0; i < qc->ngroups; i++)
     {
       tab_text_format (t, (i + 1), currow, TAB_CENTER, "%d", (i + 1));
     }
   currow++;
   tab_hline (t, TAL_1, 1, nc - 1, currow);
   currow++;
-  for (i = 0; i < kmeans->m; i++)
+  for (i = 0; i < qc->n_vars; i++)
     {
       tab_text (t, 0, currow + i, TAB_LEFT,
-               var_to_string (kmeans->variables[i]));
+               var_to_string (qc->vars[i]));
     }
 
-  for (i = 0; i < kmeans->ngroups; i++)
+  for (i = 0; i < qc->ngroups; i++)
     {
-      for (j = 0; j < kmeans->m; j++)
+      for (j = 0; j < qc->n_vars; j++)
        {
          if (!initial)
            {
              tab_double (t, i + 1, j + 4, TAB_CENTER,
                          gsl_matrix_get (kmeans->centers,
                                          kmeans->group_order->data[i], j),
-                         var_get_print_format (kmeans->variables[j]));
+                         var_get_print_format (qc->vars[j]));
            }
          else
            {
              tab_double (t, i + 1, j + 4, TAB_CENTER,
                          gsl_matrix_get (kmeans->initial_centers,
                                          kmeans->group_order->data[i], j),
-                         var_get_print_format (kmeans->variables[j]));
+                         var_get_print_format (qc->vars[j]));
            }
        }
     }
@@ -457,14 +449,14 @@ quick_cluster_show_centers (struct Kmeans *kmeans, bool initial)
 
 /* Reports number of cases of each single cluster. */
 static void
-quick_cluster_show_number_cases (struct Kmeans *kmeans)
+quick_cluster_show_number_cases (struct Kmeans *kmeans, const struct qc *qc)
 {
   struct tab_table *t;
   int nc, nr;
   int i, numelem;
   long int total;
   nc = 3;
-  nr = kmeans->ngroups + 1;
+  nr = qc->ngroups + 1;
   t = tab_create (nc, nr);
   tab_headers (t, 0, nc - 1, 0, 0);
   tab_title (t, _("Number of Cases in each Cluster"));
@@ -472,7 +464,7 @@ quick_cluster_show_number_cases (struct Kmeans *kmeans)
   tab_text (t, 0, 0, TAB_LEFT, _("Cluster"));
 
   total = 0;
-  for (i = 0; i < kmeans->ngroups; i++)
+  for (i = 0; i < qc->ngroups; i++)
     {
       tab_text_format (t, 1, i, TAB_CENTER, "%d", (i + 1));
       numelem =
@@ -481,44 +473,71 @@ quick_cluster_show_number_cases (struct Kmeans *kmeans)
       total += numelem;
     }
 
-  tab_text (t, 0, kmeans->ngroups, TAB_LEFT, _("Valid"));
-  tab_text_format (t, 2, kmeans->ngroups, TAB_LEFT, "%ld", total);
+  tab_text (t, 0, qc->ngroups, TAB_LEFT, _("Valid"));
+  tab_text_format (t, 2, qc->ngroups, TAB_LEFT, "%ld", total);
   tab_submit (t);
 }
 
 /* Reports. */
 static void
-quick_cluster_show_results (struct Kmeans *kmeans)
+quick_cluster_show_results (struct Kmeans *kmeans, const struct qc *qc)
 {
-  kmeans_order_groups (kmeans);
+  kmeans_order_groups (kmeans, qc);
   /* Uncomment the line below for reporting initial centers. */
   /* quick_cluster_show_centers (kmeans, true); */
-  quick_cluster_show_centers (kmeans, false);
-  quick_cluster_show_number_cases (kmeans);
+  quick_cluster_show_centers (kmeans, false, qc);
+  quick_cluster_show_number_cases (kmeans, qc);
 }
 
 int
 cmd_quick_cluster (struct lexer *lexer, struct dataset *ds)
 {
+  struct qc qc;
   struct Kmeans *kmeans;
   bool ok;
   const struct dictionary *dict = dataset_dict (ds);
-  const struct variable **variables;
-  struct casereader *cs;
-  int groups = 2;
-  int maxiter = 2;
-  size_t p;
+  qc.ngroups = 2;
+  qc.maxiter = 2;
+  qc.missing_type = MISS_LISTWISE;
+  qc.exclude = MV_ANY;
 
-  if (!parse_variables_const (lexer, dict, &variables, &p,
+  if (!parse_variables_const (lexer, dict, &qc.vars, &qc.n_vars,
                              PV_NO_DUPLICATE | PV_NUMERIC))
     {
-      msg (ME, _("Variables cannot be parsed"));
       return (CMD_FAILURE);
     }
 
-  if (lex_match (lexer, T_SLASH))
+  while (lex_token (lexer) != T_ENDCMD)
     {
-      if (lex_match_id (lexer, "CRITERIA"))
+      lex_match (lexer, T_SLASH);
+
+      if (lex_match_id (lexer, "MISSING"))
+       {
+         lex_match (lexer, T_EQUALS);
+         while (lex_token (lexer) != T_ENDCMD
+                && lex_token (lexer) != T_SLASH)
+           {
+             if (lex_match_id (lexer, "LISTWISE") || lex_match_id (lexer, "DEFAULT"))
+               {
+                 qc.missing_type = MISS_LISTWISE;
+               }
+             else if (lex_match_id (lexer, "PAIRWISE"))
+               {
+                 qc.missing_type = MISS_PAIRWISE;
+               }
+             else if (lex_match_id (lexer, "INCLUDE"))
+               {
+                 qc.exclude = MV_SYSTEM;
+               }
+             else if (lex_match_id (lexer, "EXCLUDE"))
+               {
+                 qc.exclude = MV_ANY;
+               }
+             else
+               goto error;
+           }     
+       }
+      else if (lex_match_id (lexer, "CRITERIA"))
        {
          lex_match (lexer, T_EQUALS);
          while (lex_token (lexer) != T_ENDCMD
@@ -529,7 +548,7 @@ cmd_quick_cluster (struct lexer *lexer, struct dataset *ds)
                  if (lex_force_match (lexer, T_LPAREN))
                    {
                      lex_force_int (lexer);
-                     groups = lex_integer (lexer);
+                     qc.ngroups = lex_integer (lexer);
                      lex_get (lexer);
                      lex_force_match (lexer, T_RPAREN);
                    }
@@ -539,27 +558,47 @@ cmd_quick_cluster (struct lexer *lexer, struct dataset *ds)
                  if (lex_force_match (lexer, T_LPAREN))
                    {
                      lex_force_int (lexer);
-                     maxiter = lex_integer (lexer);
+                     qc.maxiter = lex_integer (lexer);
                      lex_get (lexer);
                      lex_force_match (lexer, T_RPAREN);
                    }
                }
              else
-                return CMD_FAILURE;
+                goto error;
            }
        }
     }
 
-  cs = proc_open (ds);
-
-  kmeans = kmeans_create (cs, variables, p, groups, maxiter);
-
-  kmeans->wv = dict_get_weight (dict);
-  kmeans_cluster (kmeans);
-  quick_cluster_show_results (kmeans);
-  ok = proc_commit (ds);
-
-  kmeans_destroy (kmeans);
+  qc.wv = dict_get_weight (dict);
+
+  {
+    struct casereader *group;
+    struct casegrouper *grouper = casegrouper_create_splits (proc_open (ds), dict);
+
+    while (casegrouper_get_next_group (grouper, &group))
+      {
+       if ( qc.missing_type == MISS_LISTWISE )
+         {
+           group  = casereader_create_filter_missing (group, qc.vars, qc.n_vars,
+                                                    qc.exclude,
+                                                    NULL,  NULL);
+         }
+
+       kmeans = kmeans_create (&qc);
+       kmeans_cluster (kmeans, group, &qc);
+       quick_cluster_show_results (kmeans, &qc);
+       kmeans_destroy (kmeans);
+       casereader_destroy (group);
+      }
+    ok = casegrouper_destroy (grouper);
+  }
+  ok = proc_commit (ds) && ok;
+
+  free (qc.vars);
 
   return (ok);
+
+ error:
+  free (qc.vars);
+  return CMD_FAILURE;
 }
index 9fc571cf9293bd9d47aa2e4025baf4b6f11723f0..7e36065730a27818b73f92973f38739840e69c66 100644 (file)
@@ -384,7 +384,7 @@ show_runs_result (const struct runs_test *rt, const struct run_state *rs, const
            TAT_TITLE | TAB_LEFT , _("Cases < Test Value"));
 
   tab_text (table,  0, column_headers + 2,
-           TAT_TITLE | TAB_LEFT , _("Cases >= Test Value"));
+           TAT_TITLE | TAB_LEFT , _("Cases  Test Value"));
 
   tab_text (table,  0, column_headers + 3,
            TAT_TITLE | TAB_LEFT , _("Total Cases"));
diff --git a/src/language/stats/t-test-indep.c b/src/language/stats/t-test-indep.c
new file mode 100644 (file)
index 0000000..bc42e32
--- /dev/null
@@ -0,0 +1,389 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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 "t-test.h"
+
+#include <gsl/gsl_cdf.h>
+#include <math.h>
+#include "libpspp/misc.h"
+
+#include "libpspp/str.h"
+#include "data/casereader.h"
+#include "data/dictionary.h"
+#include "data/format.h"
+#include "data/variable.h"
+
+#include "math/moments.h"
+#include "math/levene.h"
+
+#include <output/tab.h>
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+
+struct indep_samples
+{
+  const struct variable *gvar;
+  bool cut;
+  const union value *gval0;
+  const union value *gval1;
+};
+
+struct pair_stats
+{
+  struct moments *mom[2];
+  double lev ;
+  struct levene *nl;
+};
+
+
+static void indep_summary (const struct tt *tt, struct indep_samples *is, const struct pair_stats *ps);
+static void indep_test (const struct tt *tt, const struct pair_stats *ps);
+
+static int
+which_group (const union value *v, const struct indep_samples *is)
+{
+  int width = var_get_width (is->gvar);
+  int cmp = value_compare_3way (v, is->gval0, width);
+  if ( is->cut )
+    return  (cmp < 0);
+
+  if (cmp == 0)
+    return 0;
+
+  if (0 == value_compare_3way (v, is->gval1, width))
+    return 1;
+
+  return -1;
+}
+
+void
+indep_run (struct tt *tt, const struct variable *gvar,
+          bool cut,
+          const union value *gval0, const union value *gval1,
+          struct casereader *reader)
+{
+  struct indep_samples is;
+  struct ccase *c;
+  struct casereader *r;
+
+  struct pair_stats *ps = xcalloc (sizeof (*ps), tt->n_vars);
+
+  int v;
+
+  for (v = 0; v < tt->n_vars; ++v)
+    {
+      ps[v].mom[0] = moments_create (MOMENT_VARIANCE);
+      ps[v].mom[1] = moments_create (MOMENT_VARIANCE);
+      ps[v].nl = levene_create (var_get_width (gvar), cut ? gval0: NULL);
+    }
+
+  is.gvar = gvar;
+  is.gval0 = gval0;
+  is.gval1 = gval1;
+  is.cut = cut;
+
+  r = casereader_clone (reader);
+  for ( ; (c = casereader_read (r) ); case_unref (c))
+    {
+      double w = dict_get_case_weight (tt->dict, c, NULL);
+
+      const union value *gv = case_data (c, gvar);
+      
+      int grp = which_group (gv, &is);
+      if ( grp < 0)
+       continue;
+
+      for (v = 0; v < tt->n_vars; ++v)
+       {
+         const union value *val = case_data (c, tt->vars[v]);
+         if (var_is_value_missing (tt->vars[v], val, tt->exclude))
+           continue;
+
+         moments_pass_one (ps[v].mom[grp], val->f, w);
+         levene_pass_one (ps[v].nl, val->f, w, gv);
+       }
+    }
+  casereader_destroy (r);
+
+  r = casereader_clone (reader);
+  for ( ; (c = casereader_read (r) ); case_unref (c))
+    {
+      double w = dict_get_case_weight (tt->dict, c, NULL);
+
+      const union value *gv = case_data (c, gvar);
+
+      int grp = which_group (gv, &is);
+      if ( grp < 0)
+       continue;
+
+      for (v = 0; v < tt->n_vars; ++v)
+       {
+         const union value *val = case_data (c, tt->vars[v]);
+         if (var_is_value_missing (tt->vars[v], val, tt->exclude))
+           continue;
+
+         moments_pass_two (ps[v].mom[grp], val->f, w);
+         levene_pass_two (ps[v].nl, val->f, w, gv);
+       }
+    }
+  casereader_destroy (r);
+
+  r = reader;
+  for ( ; (c = casereader_read (r) ); case_unref (c))
+    {
+      double w = dict_get_case_weight (tt->dict, c, NULL);
+
+      const union value *gv = case_data (c, gvar);
+
+      int grp = which_group (gv, &is);
+      if ( grp < 0)
+       continue;
+
+      for (v = 0; v < tt->n_vars; ++v)
+       {
+         const union value *val = case_data (c, tt->vars[v]);
+         if (var_is_value_missing (tt->vars[v], val, tt->exclude))
+           continue;
+
+         levene_pass_three (ps[v].nl, val->f, w, gv);
+       }
+    }
+  casereader_destroy (r);
+
+
+  for (v = 0; v < tt->n_vars; ++v)
+    ps[v].lev = levene_calculate (ps[v].nl);
+  
+  indep_summary (tt, &is, ps);
+  indep_test (tt, ps);
+
+
+  for (v = 0; v < tt->n_vars; ++v)
+    {
+      moments_destroy (ps[v].mom[0]);
+      moments_destroy (ps[v].mom[1]);
+      levene_destroy (ps[v].nl);
+    }
+  free (ps);
+}
+
+
+static void
+indep_summary (const struct tt *tt, struct indep_samples *is, const struct pair_stats *ps)
+{
+  const struct fmt_spec *wfmt = tt->wv ? var_get_print_format (tt->wv) : & F_8_0;
+
+  int v;
+  int cols = 6;
+  const int heading_rows = 1;
+  int rows = tt->n_vars * 2 + heading_rows;
+
+  struct string vallab0 ;
+  struct string vallab1 ;
+  struct tab_table *t = tab_create (cols, rows);
+
+  ds_init_empty (&vallab0);
+  ds_init_empty (&vallab1);
+
+  tab_headers (t, 0, 0, 1, 0);
+  tab_box (t, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols - 1, rows - 1);
+  tab_hline (t, TAL_2, 0, cols - 1, 1);
+
+  tab_vline (t, TAL_GAP, 1, 0, rows - 1);
+  tab_title (t, _("Group Statistics"));
+  tab_text  (t, 1, 0, TAB_CENTER | TAT_TITLE, var_to_string (is->gvar));
+  tab_text  (t, 2, 0, TAB_CENTER | TAT_TITLE, _("N"));
+  tab_text  (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Mean"));
+  tab_text  (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
+  tab_text  (t, 5, 0, TAB_CENTER | TAT_TITLE, _("S.E. Mean"));
+
+  if (is->cut)
+    {
+      ds_put_cstr (&vallab0, "≥");
+      ds_put_cstr (&vallab1, "<");
+
+      var_append_value_name (is->gvar, is->gval0, &vallab0);
+      var_append_value_name (is->gvar, is->gval0, &vallab1);
+    }
+  else
+    {
+      var_append_value_name (is->gvar, is->gval0, &vallab0);
+      var_append_value_name (is->gvar, is->gval1, &vallab1);
+    }
+
+  for (v = 0; v < tt->n_vars; ++v)
+    {
+      int i;
+      const struct variable *var = tt->vars[v];
+
+      tab_text (t, 0, v * 2 + heading_rows, TAB_LEFT,
+                var_to_string (var));
+
+      tab_text (t, 1, v * 2 + heading_rows, TAB_LEFT,
+                       ds_cstr (&vallab0));
+
+      tab_text (t, 1, v * 2 + 1 + heading_rows, TAB_LEFT,
+                       ds_cstr (&vallab1));
+
+      for (i = 0 ; i < 2; ++i)
+       {
+         double cc, mean, sigma;
+         moments_calculate (ps[v].mom[i], &cc, &mean, &sigma, NULL, NULL);
+      
+         tab_double (t, 2, v * 2 + i + heading_rows, TAB_RIGHT, cc, wfmt);
+         tab_double (t, 3, v * 2 + i + heading_rows, TAB_RIGHT, mean, NULL);
+         tab_double (t, 4, v * 2 + i + heading_rows, TAB_RIGHT, sqrt (sigma), NULL);
+         tab_double (t, 5, v * 2 + i + heading_rows, TAB_RIGHT, sqrt (sigma / cc), NULL);
+       }
+    }
+
+  tab_submit (t);
+
+  ds_destroy (&vallab0);
+  ds_destroy (&vallab1);
+}
+
+
+static void
+indep_test (const struct tt *tt, const struct pair_stats *ps)
+{
+  int v;
+  const int heading_rows = 3;
+  const int rows= tt->n_vars * 2 + heading_rows;
+
+  const size_t cols = 11;
+
+  struct tab_table *t = tab_create (cols, rows);
+  tab_headers (t, 0, 0, 3, 0);
+  tab_box (t, TAL_2, TAL_2, TAL_0, TAL_0, 0, 0, cols - 1, rows - 1);
+  tab_hline (t, TAL_2, 0, cols - 1, 3);
+
+  tab_title (t, _("Independent Samples Test"));
+
+  tab_hline (t, TAL_1, 2, cols - 1, 1);
+  tab_vline (t, TAL_2, 2, 0, rows - 1);
+  tab_vline (t, TAL_1, 4, 0, rows - 1);
+  tab_box (t, -1, -1, -1, TAL_1, 2, 1, cols - 2, rows - 1);
+  tab_hline (t, TAL_1, cols - 2, cols - 1, 2);
+  tab_box (t, -1, -1, -1, TAL_1, cols - 2, 2, cols - 1, rows - 1);
+  tab_joint_text (t, 2, 0, 3, 0, TAB_CENTER, _("Levene's Test for Equality of Variances"));
+  tab_joint_text (t, 4, 0, cols - 1, 0, TAB_CENTER, _("t-test for Equality of Means"));
+
+  tab_text (t, 2, 2, TAB_CENTER | TAT_TITLE, _("F"));
+  tab_text (t, 3, 2, TAB_CENTER | TAT_TITLE, _("Sig."));
+  tab_text (t, 4, 2, TAB_CENTER | TAT_TITLE, _("t"));
+  tab_text (t, 5, 2, TAB_CENTER | TAT_TITLE, _("df"));
+  tab_text (t, 6, 2, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
+  tab_text (t, 7, 2, TAB_CENTER | TAT_TITLE, _("Mean Difference"));
+  tab_text (t, 8, 2, TAB_CENTER | TAT_TITLE, _("Std. Error Difference"));
+  tab_text (t, 9, 2, TAB_CENTER | TAT_TITLE, _("Lower"));
+  tab_text (t, 10, 2, TAB_CENTER | TAT_TITLE, _("Upper"));
+
+  tab_joint_text_format (t, 9, 1, 10, 1, TAB_CENTER,
+                         _("%g%% Confidence Interval of the Difference"),
+                         tt->confidence * 100.0);
+
+  for (v = 0; v < tt->n_vars; ++v)
+  {
+    double df, pooled_variance, mean_diff, tval;
+    double se2, std_err_diff;
+    double p, q;
+    double cc0, mean0, sigma0;
+    double cc1, mean1, sigma1;
+    moments_calculate (ps[v].mom[0], &cc0, &mean0, &sigma0, NULL, NULL);
+    moments_calculate (ps[v].mom[1], &cc1, &mean1, &sigma1, NULL, NULL);
+
+    tab_text (t, 0, v * 2 + heading_rows, TAB_LEFT, var_to_string (tt->vars[v]));
+    tab_text (t, 1, v * 2 + heading_rows, TAB_LEFT, _("Equal variances assumed"));
+
+    df = cc0 + cc1 - 2.0;
+    tab_double (t, 5, v * 2 + heading_rows, TAB_RIGHT, df, NULL);
+    
+    pooled_variance = ((cc0 - 1)* sigma0 + (cc1 - 1) * sigma1) / df ;
+
+    tval = (mean0 - mean1) / sqrt (pooled_variance);
+    tval /= sqrt ((cc0 + cc1) / (cc0 * cc1));
+
+    tab_double (t, 4, v * 2 + heading_rows, TAB_RIGHT, tval, NULL);
+
+    p = gsl_cdf_tdist_P (tval, df);
+    q = gsl_cdf_tdist_Q (tval, df);
+
+    mean_diff = mean0 - mean1;
+
+    tab_double (t, 6, v * 2 + heading_rows, TAB_RIGHT, 2.0 * (tval > 0 ? q : p),   NULL);
+    tab_double (t, 7, v * 2 + heading_rows, TAB_RIGHT, mean_diff, NULL);
+
+    std_err_diff = sqrt ((sigma0 / cc0) + (sigma1 / cc1));
+    tab_double (t, 8, v * 2 + heading_rows, TAB_RIGHT, std_err_diff, NULL);
+
+
+    /* Now work out the confidence interval */
+    q = (1 - tt->confidence)/2.0;  /* 2-tailed test */
+
+    tval = gsl_cdf_tdist_Qinv (q, df);
+    tab_double (t,  9, v * 2 + heading_rows, TAB_RIGHT, mean_diff - tval * std_err_diff, NULL);
+    tab_double (t, 10, v * 2 + heading_rows, TAB_RIGHT, mean_diff + tval * std_err_diff, NULL);
+
+    /* Equal variances not assumed */
+    tab_text (t, 1, v * 2 + heading_rows + 1,  TAB_LEFT, _("Equal variances not assumed"));
+
+    se2 = sigma0 / cc0 + sigma1 / cc1;
+    tval = mean_diff / sqrt (se2);
+    tab_double (t, 4, v * 2 + heading_rows + 1, TAB_RIGHT, tval, NULL);
+
+    {
+      double p, q;
+      const double s0 = sigma0 / (cc0);
+      const double s1 = sigma1 / (cc1);
+      double df = pow2 (s0 + s1) ;
+      df /= pow2 (s0) / (cc0 - 1) + pow2 (s1) / (cc1 - 1);
+
+      tab_double (t, 5, v * 2 + heading_rows + 1, TAB_RIGHT, df, NULL);
+
+      p = gsl_cdf_tdist_P (tval, df);
+      q = gsl_cdf_tdist_Q (tval, df);
+
+      tab_double (t, 6, v * 2 + heading_rows + 1, TAB_RIGHT, 2.0 * (tval > 0 ? q : p), NULL);
+
+      /* Now work out the confidence interval */
+      q = (1 - tt->confidence) / 2.0;  /* 2-tailed test */
+
+      tval = gsl_cdf_tdist_Qinv (q, df);
+    }
+
+    tab_double (t, 7, v * 2 + heading_rows + 1, TAB_RIGHT, mean_diff, NULL);
+    tab_double (t, 8, v * 2 + heading_rows + 1, TAB_RIGHT, std_err_diff, NULL);
+    tab_double (t, 9, v * 2 + heading_rows + 1, TAB_RIGHT,  mean_diff - tval * std_err_diff, NULL);
+    tab_double (t, 10, v * 2 + heading_rows + 1, TAB_RIGHT, mean_diff + tval * std_err_diff, NULL);
+
+    tab_double (t, 2, v * 2 + heading_rows, TAB_CENTER, ps[v].lev, NULL);
+
+
+    {
+      /* Now work out the significance of the Levene test */
+      double df1 = 1;
+      double df2 = cc0 + cc1 - 2;
+      double q = gsl_cdf_fdist_Q (ps[v].lev, df1, df2);
+      tab_double (t, 3, v * 2 + heading_rows, TAB_CENTER, q, NULL);
+    }
+  }
+
+  tab_submit (t);
+}
diff --git a/src/language/stats/t-test-one-sample.c b/src/language/stats/t-test-one-sample.c
new file mode 100644 (file)
index 0000000..38c1eff
--- /dev/null
@@ -0,0 +1,253 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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 "t-test.h"
+
+#include <math.h>
+#include <gsl/gsl_cdf.h>
+
+#include "data/variable.h"
+#include "data/format.h"
+#include "data/casereader.h"
+#include "data/dictionary.h"
+#include "libpspp/hash-functions.h"
+#include "libpspp/hmapx.h"
+#include "math/moments.h"
+
+#include "output/tab.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+
+struct per_var_stats
+{
+  const struct variable *var;
+
+  /* The position for reporting purposes */
+  int posn;
+
+  /* N, Mean, Variance */
+  struct moments *mom;
+
+  /* Sum of the differences */
+  double sum_diff;
+};
+
+
+struct one_samp
+{
+  struct hmapx hmap;
+  double testval;
+};
+
+
+static void
+one_sample_test (const struct tt *tt, const struct one_samp *os)
+{
+  struct hmapx_node *node;
+  struct per_var_stats *per_var_stats;
+
+  const int heading_rows = 3;
+  const size_t rows = heading_rows + tt->n_vars;
+  const size_t cols = 7;
+  const struct fmt_spec *wfmt = tt->wv ? var_get_print_format (tt->wv) : & F_8_0;
+
+  struct tab_table *t = tab_create (cols, rows);
+
+  tab_headers (t, 0, 0, heading_rows, 0);
+  tab_box (t, TAL_2, TAL_2, TAL_0, TAL_0, 0, 0, cols - 1, rows - 1);
+  tab_hline (t, TAL_2, 0, cols - 1, 3);
+
+  tab_title (t, _("One-Sample Test"));
+  tab_hline (t, TAL_1, 1, cols - 1, 1);
+  tab_vline (t, TAL_2, 1, 0, rows - 1);
+
+  tab_joint_text_format (t, 1, 0, cols - 1, 0, TAB_CENTER,
+                         _("Test Value = %f"), os->testval);
+
+  tab_box (t, -1, -1, -1, TAL_1, 1, 1, cols - 1, rows - 1);
+
+  tab_joint_text_format (t, 5, 1, 6, 1, TAB_CENTER,
+                         _("%g%% Confidence Interval of the Difference"),
+                         tt->confidence * 100.0);
+
+  tab_vline (t, TAL_GAP, 6, 1, 1);
+  tab_hline (t, TAL_1, 5, 6, 2);
+  tab_text (t, 1, 2, TAB_CENTER | TAT_TITLE, _("t"));
+  tab_text (t, 2, 2, TAB_CENTER | TAT_TITLE, _("df"));
+  tab_text (t, 3, 2, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
+  tab_text (t, 4, 2, TAB_CENTER | TAT_TITLE, _("Mean Difference"));
+  tab_text (t, 5, 2, TAB_CENTER | TAT_TITLE, _("Lower"));
+  tab_text (t, 6, 2, TAB_CENTER | TAT_TITLE, _("Upper"));
+
+  HMAPX_FOR_EACH (per_var_stats, node, &os->hmap)
+    {
+      const struct moments *m = per_var_stats->mom;
+      double cc, mean, sigma;
+      double tval, df;
+      double p, q;
+      double mean_diff;
+      double se_mean ;
+      const int v = per_var_stats->posn;
+
+      moments_calculate (m, &cc, &mean, &sigma, NULL, NULL);
+
+      tval = (mean - os->testval) * sqrt (cc / sigma);
+
+      mean_diff = per_var_stats->sum_diff / cc;
+      se_mean = sqrt (sigma / cc);
+      df = cc - 1.0;
+      p = gsl_cdf_tdist_P (tval, df);
+      q = gsl_cdf_tdist_Q (tval, df);
+
+      tab_text (t, 0, v + heading_rows, TAB_LEFT, var_to_string (per_var_stats->var));
+      tab_double (t, 1, v + heading_rows, TAB_RIGHT, tval, NULL);
+      tab_double (t, 2, v + heading_rows, TAB_RIGHT, df, wfmt);
+
+      /* Multiply by 2 to get 2-tailed significance, makeing sure we've got
+        the correct tail*/
+      tab_double (t, 3, v + heading_rows, TAB_RIGHT, 2.0 * (tval > 0 ? q : p), NULL);
+
+      tab_double (t, 4, v + heading_rows, TAB_RIGHT, mean_diff,  NULL);
+
+      tval = gsl_cdf_tdist_Qinv ( (1.0 - tt->confidence) / 2.0, df);
+
+      tab_double (t, 5, v + heading_rows, TAB_RIGHT, mean_diff - tval * se_mean, NULL);
+      tab_double (t, 6, v + heading_rows, TAB_RIGHT, mean_diff + tval * se_mean, NULL);
+    }
+
+  tab_submit (t);
+}
+
+static void
+one_sample_summary (const struct tt *tt, const struct one_samp *os)
+{
+  struct hmapx_node *node;
+  struct per_var_stats *per_var_stats;
+
+  const int cols = 5;
+  const int heading_rows = 1;
+  const int rows = tt->n_vars + heading_rows;
+  struct tab_table *t = tab_create (cols, rows);
+  const struct fmt_spec *wfmt = tt->wv ? var_get_print_format (tt->wv) : & F_8_0;
+
+  tab_headers (t, 0, 0, heading_rows, 0);
+  tab_box (t, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols - 1, rows - 1);
+  tab_hline (t, TAL_2, 0, cols - 1, 1);
+
+  tab_title (t, _("One-Sample Statistics"));
+  tab_vline (t, TAL_2, 1, 0, rows - 1);
+  tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("N"));
+  tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("Mean"));
+  tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
+  tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("S.E. Mean"));
+
+  HMAPX_FOR_EACH (per_var_stats, node, &os->hmap)
+    {
+      const struct moments *m = per_var_stats->mom;
+      const int v = per_var_stats->posn;
+      double cc, mean, sigma;
+      moments_calculate (m, &cc, &mean, &sigma, NULL, NULL);
+
+      tab_text (t, 0, v + heading_rows, TAB_LEFT, var_to_string (per_var_stats->var));
+      tab_double (t, 1, v + heading_rows, TAB_RIGHT, cc, wfmt);
+      tab_double (t, 2, v + heading_rows, TAB_RIGHT, mean, NULL);
+      tab_double (t, 3, v + heading_rows, TAB_RIGHT, sqrt (sigma), NULL);
+      tab_double (t, 4, v + heading_rows, TAB_RIGHT, sqrt (sigma / cc), NULL);
+    }
+
+  tab_submit (t);
+}
+
+void
+one_sample_run (const struct tt *tt, double testval, struct casereader *reader)
+{
+  int i;
+  struct ccase *c;
+  struct one_samp os;
+  struct casereader *r;
+  struct hmapx_node *node;
+  struct per_var_stats *per_var_stats;
+
+  os.testval = testval;
+  hmapx_init (&os.hmap);
+
+  /* Insert all the variables into the map */
+  for (i = 0; i < tt->n_vars; ++i)
+    {
+      struct per_var_stats *per_var_stats = xzalloc (sizeof (*per_var_stats));
+
+      per_var_stats->posn = i;
+      per_var_stats->var = tt->vars[i];
+      per_var_stats->mom = moments_create (MOMENT_VARIANCE);
+
+      hmapx_insert (&os.hmap, per_var_stats, hash_pointer (per_var_stats->var, 0));
+    }
+
+  r = casereader_clone (reader);
+  for ( ; (c = casereader_read (r) ); case_unref (c))
+    {
+      double w = dict_get_case_weight (tt->dict, c, NULL);
+      struct hmapx_node *node;
+      struct per_var_stats *per_var_stats;
+      HMAPX_FOR_EACH (per_var_stats, node, &os.hmap)
+       {
+         const struct variable *var = per_var_stats->var;
+         const union value *val = case_data (c, var);
+         if (var_is_value_missing (var, val, tt->exclude))
+           continue;
+
+         moments_pass_one (per_var_stats->mom, val->f, w);
+       }
+    }
+  casereader_destroy (r);
+
+  r = reader;
+  for ( ; (c = casereader_read (r) ); case_unref (c))
+    {
+      double w = dict_get_case_weight (tt->dict, c, NULL);
+      struct hmapx_node *node;
+      struct per_var_stats *per_var_stats;
+      HMAPX_FOR_EACH (per_var_stats, node, &os.hmap)
+       {
+         const struct variable *var = per_var_stats->var;
+         const union value *val = case_data (c, var);
+         if (var_is_value_missing (var, val, tt->exclude))
+           continue;
+
+         moments_pass_two (per_var_stats->mom, val->f, w);
+         per_var_stats->sum_diff += w * (val->f - os.testval);
+       }
+    }
+  casereader_destroy (r);
+
+  one_sample_summary (tt, &os);
+  one_sample_test (tt, &os);
+
+  HMAPX_FOR_EACH (per_var_stats, node, &os.hmap)
+    {
+      moments_destroy (per_var_stats->mom);
+      free (per_var_stats);
+    }
+
+  hmapx_destroy (&os.hmap);
+}
+
diff --git a/src/language/stats/t-test-paired.c b/src/language/stats/t-test-paired.c
new file mode 100644 (file)
index 0000000..edeaa38
--- /dev/null
@@ -0,0 +1,356 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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 <math.h>
+#include <gsl/gsl_cdf.h>
+
+#include "t-test.h"
+
+#include "math/moments.h"
+#include "math/correlation.h"
+#include "data/casereader.h"
+#include "data/dictionary.h"
+#include "data/format.h"
+#include "data/variable.h"
+#include "libpspp/hmapx.h"
+#include "libpspp/hash-functions.h"
+
+#include "output/tab.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+
+struct pair_stats
+{
+  int posn;
+  double sum_of_prod;
+  struct moments *mom0;
+  const struct variable *var0;
+
+  struct moments *mom1;
+  const struct variable *var1;
+
+  struct moments *mom_diff;
+};
+
+struct paired_samp
+{
+  struct hmapx hmap;
+};
+
+static void paired_summary (const struct tt *tt, struct paired_samp *os);
+static void paired_correlations (const struct tt *tt, struct paired_samp *os);
+static void paired_test (const struct tt *tt, const struct paired_samp *os);
+
+void
+paired_run (const struct tt *tt, size_t n_pairs, vp *pairs, struct casereader *reader)
+{
+  int i;
+  struct ccase *c;
+  struct paired_samp ps;
+  struct casereader *r;
+  struct hmapx_node *node;
+  struct pair_stats *pp = NULL;
+
+  hmapx_init (&ps.hmap);
+
+  for (i = 0; i < n_pairs; ++i)
+    {
+      vp *pair = &pairs[i];
+      unsigned int hash;
+      struct pair_stats *pp = xzalloc (sizeof *pp);
+      pp->posn = i;
+      pp->var0 = (*pair)[0];
+      pp->var1 = (*pair)[1];
+      pp->mom0 = moments_create (MOMENT_VARIANCE);
+      pp->mom1 = moments_create (MOMENT_VARIANCE);
+      pp->mom_diff = moments_create (MOMENT_VARIANCE);
+
+      hash = hash_pointer ((*pair)[0], 0);
+      hash = hash_pointer ((*pair)[1], hash);
+
+      hmapx_insert (&ps.hmap, pp, hash);
+    }
+
+  r = casereader_clone (reader);
+  for ( ; (c = casereader_read (r) ); case_unref (c))
+    {
+      double w = dict_get_case_weight (tt->dict, c, NULL);
+
+      struct hmapx_node *node;
+      struct pair_stats *pp = NULL;
+      HMAPX_FOR_EACH (pp, node, &ps.hmap)
+       {
+         const union value *val0 = case_data (c, pp->var0);
+         const union value *val1 = case_data (c, pp->var1);
+          if (var_is_value_missing (pp->var0, val0, tt->exclude))
+           continue;
+
+          if (var_is_value_missing (pp->var1, val1, tt->exclude))
+           continue;
+
+         moments_pass_one (pp->mom0, val0->f, w);
+         moments_pass_one (pp->mom1, val1->f, w);
+         moments_pass_one (pp->mom_diff, val0->f - val1->f, w);
+       }
+    }
+  casereader_destroy (r);
+
+  r = reader;
+  for ( ; (c = casereader_read (r) ); case_unref (c))
+    {
+      double w = dict_get_case_weight (tt->dict, c, NULL);
+
+      struct hmapx_node *node;
+      struct pair_stats *pp = NULL;
+      HMAPX_FOR_EACH (pp, node, &ps.hmap)
+       {
+         const union value *val0 = case_data (c, pp->var0);
+         const union value *val1 = case_data (c, pp->var1);
+          if (var_is_value_missing (pp->var0, val0, tt->exclude))
+           continue;
+
+          if (var_is_value_missing (pp->var1, val1, tt->exclude))
+           continue;
+
+         moments_pass_two (pp->mom0, val0->f, w);
+         moments_pass_two (pp->mom1, val1->f, w);
+         moments_pass_two (pp->mom_diff, val0->f - val1->f, w);
+         pp->sum_of_prod += val0->f * val1->f;
+       }
+    }
+  casereader_destroy (r);
+
+  paired_summary (tt, &ps);
+  paired_correlations (tt, &ps);
+  paired_test (tt, &ps);
+
+  /* Clean up */
+  HMAPX_FOR_EACH (pp, node, &ps.hmap)
+    {
+      moments_destroy (pp->mom0);
+      moments_destroy (pp->mom1);
+      moments_destroy (pp->mom_diff);
+      free (pp);
+    }
+
+  hmapx_destroy (&ps.hmap);
+}
+
+static void
+paired_summary (const struct tt *tt, struct paired_samp *os)
+{
+  size_t n_pairs = hmapx_count (&os->hmap);
+  struct hmapx_node *node;
+  struct pair_stats *pp = NULL;
+
+  const int heading_rows = 1;
+  const int heading_cols = 2;
+
+  const int cols = 4 + heading_cols;
+  const int rows = n_pairs * 2 + heading_rows;
+  struct tab_table *t = tab_create (cols, rows);
+  const struct fmt_spec *wfmt = tt->wv ? var_get_print_format (tt->wv) : & F_8_0;
+
+  tab_headers (t, 0, 0, heading_rows, 0);
+  tab_box (t, TAL_2, TAL_2, TAL_0, TAL_0, 0, 0, cols - 1, rows - 1);
+  tab_box (t, -1, -1,       TAL_0, TAL_1, heading_cols, 0, cols - 1, rows - 1);
+
+  tab_hline (t, TAL_2, 0, cols - 1, 1);
+
+  tab_title (t, _("Paired Sample Statistics"));
+  tab_vline (t, TAL_2, heading_cols, 0, rows - 1);
+  tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("N"));
+  tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("Mean"));
+  tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
+  tab_text (t, 5, 0, TAB_CENTER | TAT_TITLE, _("S.E. Mean"));
+
+  HMAPX_FOR_EACH (pp, node, &os->hmap)
+    {
+      int v = pp->posn;
+      double cc, mean, sigma;
+
+      tab_text_format (t, 0, v * 2 + heading_rows, TAB_LEFT, _("Pair %d"), pp->posn);
+
+      /* first var */
+      moments_calculate (pp->mom0, &cc, &mean, &sigma, NULL, NULL);
+      tab_text (t, 1, v * 2 + heading_rows, TAB_LEFT, var_to_string (pp->var0));
+      tab_double (t, 3, v * 2 + heading_rows, TAB_RIGHT, cc, wfmt);
+      tab_double (t, 2, v * 2 + heading_rows, TAB_RIGHT, mean, NULL);
+      tab_double (t, 4, v * 2 + heading_rows, TAB_RIGHT, sqrt (sigma), NULL);
+      tab_double (t, 5, v * 2 + heading_rows, TAB_RIGHT, sqrt (sigma / cc), NULL);
+
+      /* second var */
+      moments_calculate (pp->mom1, &cc, &mean, &sigma, NULL, NULL);
+      tab_text (t, 1, v * 2 + 1 + heading_rows, TAB_LEFT, var_to_string (pp->var1));      
+      tab_double (t, 3, v * 2 + 1 + heading_rows, TAB_RIGHT, cc, wfmt);
+      tab_double (t, 2, v * 2 + 1 + heading_rows, TAB_RIGHT, mean, NULL);
+      tab_double (t, 4, v * 2 + 1 + heading_rows, TAB_RIGHT, sqrt (sigma), NULL);
+      tab_double (t, 5, v * 2 + 1 + heading_rows, TAB_RIGHT, sqrt (sigma / cc), NULL);
+    }
+
+  tab_submit (t);
+}
+
+
+static void
+paired_correlations (const struct tt *tt, struct paired_samp *os)
+{
+  size_t n_pairs = hmapx_count (&os->hmap);
+  struct hmapx_node *node;
+  struct pair_stats *pp = NULL;
+  const int heading_rows = 1;
+  const int heading_cols = 2;
+
+  const int cols = 5;
+  const int rows = n_pairs + heading_rows;
+  struct tab_table *t = tab_create (cols, rows);
+  const struct fmt_spec *wfmt = tt->wv ? var_get_print_format (tt->wv) : & F_8_0;
+
+  tab_headers (t, 0, 0, heading_rows, 0);
+  tab_box (t, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols - 1, rows - 1);
+
+  tab_hline (t, TAL_2, 0, cols - 1, 1);
+
+  tab_title (t, _("Paired Samples Correlations"));
+  tab_vline (t, TAL_2, heading_cols, 0, rows - 1);
+  tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("N"));
+  tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Correlation"));
+  tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Sig."));
+
+  HMAPX_FOR_EACH (pp, node, &os->hmap)
+    {
+      double corr;
+      double cc0, mean0, sigma0;
+      double cc1, mean1, sigma1;
+      int v = pp->posn;
+
+      tab_text_format (t, 0, v + heading_rows, TAB_LEFT, _("Pair %d"), pp->posn);
+
+      tab_text_format (t, 1, v + heading_rows, TAB_LEFT, _("%s & %s"), 
+                      var_to_string (pp->var0),
+                      var_to_string (pp->var1));
+
+      moments_calculate (pp->mom0, &cc0, &mean0, &sigma0, NULL, NULL);
+      moments_calculate (pp->mom1, &cc1, &mean1, &sigma1, NULL, NULL);
+
+      /* If this fails, then we're not dealing with missing values properly */
+      assert (cc0 == cc1);
+
+      tab_double (t, 2, v + heading_rows, TAB_RIGHT, cc0, wfmt);
+
+      corr = pp->sum_of_prod / cc0  - (mean0 * mean1);
+      corr /= sqrt (sigma0 * sigma1);
+      corr *= cc0 / (cc0 - 1);
+
+      tab_double (t, 3, v + heading_rows, TAB_RIGHT, corr, NULL);
+      tab_double (t, 4, v + heading_rows, TAB_RIGHT, 
+                 2.0 * significance_of_correlation (corr, cc0), NULL);
+    }
+
+  tab_submit (t);
+}
+
+
+static void
+paired_test (const struct tt *tt, const struct paired_samp *os)
+{
+  size_t n_pairs = hmapx_count (&os->hmap);
+  struct hmapx_node *node;
+  struct pair_stats *pp = NULL;
+
+  const int heading_rows = 3;
+  const int heading_cols = 2;
+  const size_t rows = heading_rows + n_pairs;
+  const size_t cols = 10;
+  const struct fmt_spec *wfmt = tt->wv ? var_get_print_format (tt->wv) : & F_8_0;
+
+  struct tab_table *t = tab_create (cols, rows);
+
+  tab_headers (t, 0, 0, heading_rows, 0);
+  tab_box (t, TAL_2, TAL_2, TAL_0, TAL_0, 0, 0, cols - 1, rows - 1);
+  tab_hline (t, TAL_2, 0, cols - 1, 3);
+
+  tab_title (t, _("Paired Samples Test"));
+  tab_hline (t, TAL_1, heading_cols, 6, 1);
+  tab_vline (t, TAL_2, heading_cols, 0, rows - 1);
+
+  tab_box (t, -1, -1, -1, TAL_1, heading_cols, 0, cols - 1, rows - 1);
+
+  tab_joint_text (t, 2, 0, 6, 0, TAB_CENTER,
+                 _("Paired Differences"));
+
+  tab_joint_text_format (t, 5, 1, 6, 1, TAB_CENTER,
+                         _("%g%% Confidence Interval of the Difference"),
+                         tt->confidence * 100.0);
+
+  tab_vline (t, TAL_GAP, 6, 1, 1);
+  tab_hline (t, TAL_1, 5, 6, 2);
+  tab_text (t, 7, 2, TAB_CENTER | TAT_TITLE, _("t"));
+  tab_text (t, 8, 2, TAB_CENTER | TAT_TITLE, _("df"));
+  tab_text (t, 9, 2, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
+  tab_text (t, 4, 2, TAB_CENTER | TAT_TITLE, _("Std. Error Mean"));
+  tab_text (t, 3, 2, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
+  tab_text (t, 2, 2, TAB_CENTER | TAT_TITLE, _("Mean"));
+
+  tab_text (t, 5, 2, TAB_CENTER | TAT_TITLE, _("Lower"));
+  tab_text (t, 6, 2, TAB_CENTER | TAT_TITLE, _("Upper"));
+
+  HMAPX_FOR_EACH (pp, node, &os->hmap)
+    {
+      int v = pp->posn;
+      double cc, mean, sigma;
+      double df ;
+      double tval;
+      double p, q;
+      double se_mean;
+
+      moments_calculate (pp->mom_diff, &cc, &mean, &sigma, NULL, NULL);
+
+      df = cc - 1.0;
+      tab_text_format (t, 0, v + heading_rows, TAB_LEFT, _("Pair %d"), v);
+
+      tab_text_format (t, 1, v + heading_rows, TAB_LEFT, _("%s - %s"), 
+                      var_to_string (pp->var0),
+                      var_to_string (pp->var1));
+
+      tval = mean * sqrt (cc / sigma);
+      se_mean = sqrt (sigma / cc);
+
+      tab_double (t, 2, v + heading_rows, TAB_RIGHT, mean, NULL);
+      tab_double (t, 3, v + heading_rows, TAB_RIGHT, sqrt (sigma), NULL);
+      tab_double (t, 4, v + heading_rows, TAB_RIGHT, se_mean, NULL);
+
+      tab_double (t, 7, v + heading_rows, TAB_RIGHT, tval, NULL);
+      tab_double (t, 8, v + heading_rows, TAB_RIGHT, df, wfmt);
+
+
+      p = gsl_cdf_tdist_P (tval, df);
+      q = gsl_cdf_tdist_Q (tval, df);
+
+      tab_double (t, 9, v + heading_rows, TAB_RIGHT, 2.0 * (tval > 0 ? q : p), NULL);
+
+      tval = gsl_cdf_tdist_Qinv ( (1.0 - tt->confidence) / 2.0, df);
+
+      tab_double (t, 5, v + heading_rows, TAB_RIGHT, mean - tval * se_mean, NULL);
+      tab_double (t, 6, v + heading_rows, TAB_RIGHT, mean + tval * se_mean, NULL);
+    }
+
+  tab_submit (t);
+}
diff --git a/src/language/stats/t-test-parser.c b/src/language/stats/t-test-parser.c
new file mode 100644 (file)
index 0000000..7c8d8a5
--- /dev/null
@@ -0,0 +1,374 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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 "libpspp/message.h"
+
+#include "data/casegrouper.h"
+#include "data/casereader.h"
+#include "data/dictionary.h"
+#include "data/dataset.h"
+#include "data/missing-values.h"
+
+#include "language/lexer/lexer.h"
+#include "language/command.h"
+#include "language/lexer/variable-parser.h"
+#include "language/lexer/value-parser.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+#include "t-test.h"
+
+int
+cmd_t_test (struct lexer *lexer, struct dataset *ds)
+{
+  bool ok;
+  const struct dictionary *dict = dataset_dict (ds);
+  struct tt tt;
+  int mode_count = 0;
+
+  /* Variables pertaining to the paired mode */
+  const struct variable **v1 = NULL;
+  size_t n_v1;
+  const struct variable **v2 = NULL;
+  size_t n_v2;
+         
+  size_t n_pairs;
+  vp *pairs = NULL;
+
+
+  /* One sample mode */
+  double testval;
+
+  /* Independent samples mode */
+  const struct variable *gvar;
+  union value gval0;
+  union value gval1;
+  bool cut;
+
+  tt.wv = dict_get_weight (dict);
+  tt.dict = dict;
+  tt.confidence = 0.95;
+  tt.exclude = MV_ANY;
+  tt.missing_type = MISS_ANALYSIS;
+  tt.n_vars = 0;
+  tt.vars = NULL;
+  tt.mode = MODE_undef;
+
+  lex_match (lexer, T_EQUALS);
+
+  for (; lex_token (lexer) != T_ENDCMD; )
+    {
+      lex_match (lexer, T_SLASH);
+      if (lex_match_id (lexer, "TESTVAL"))
+       {
+         mode_count++;
+         tt.mode = MODE_SINGLE;
+         lex_match (lexer, T_EQUALS);
+         lex_force_num (lexer);
+         testval = lex_number (lexer);
+         lex_get (lexer);
+       }
+      else if (lex_match_id (lexer, "GROUPS"))
+       {
+         mode_count++;
+         cut = false;
+         tt.mode = MODE_INDEP;
+         lex_match (lexer, T_EQUALS);
+
+         if (NULL == (gvar = parse_variable (lexer, dict)))
+           goto parse_failed;
+      
+         if (lex_match (lexer, T_LPAREN))
+           {
+
+             value_init (&gval0, var_get_width (gvar));
+             parse_value (lexer, &gval0, gvar);
+             cut = true;
+             if (lex_match (lexer, T_COMMA))
+               {
+                 value_init (&gval1, var_get_width (gvar));
+                 parse_value (lexer, &gval1, gvar);
+                 cut = false;
+               }
+
+             lex_force_match (lexer, T_RPAREN);
+           }
+         else
+           {
+             value_init (&gval0, 0);
+             value_init (&gval1, 0);
+             gval0.f = 1.0;
+             gval1.f = 2.0;
+             cut = false;
+           }
+
+         if ( cut == true && var_is_alpha (gvar))
+           {
+             msg (SE, _("When applying GROUPS to a string variable, two "
+                        "values must be specified."));
+             goto parse_failed;
+           }
+       }
+      else if (lex_match_id (lexer, "PAIRS"))
+       {
+         bool with = false;
+         bool paired = false;
+
+         if (tt.n_vars > 0)
+           {
+             msg (SE, _("VARIABLES subcommand may not be used with PAIRS."));
+             goto parse_failed;
+           }
+
+         mode_count++;
+         tt.mode = MODE_PAIRED;
+         lex_match (lexer, T_EQUALS);
+
+         if (!parse_variables_const (lexer, dict,
+                                     &v1, &n_v1,
+                                     PV_NO_DUPLICATE | PV_NUMERIC))
+           goto parse_failed;
+
+         if ( lex_match (lexer, T_WITH))
+           {
+             with = true;
+             if (!parse_variables_const (lexer, dict,
+                                         &v2, &n_v2,
+                                         PV_NO_DUPLICATE | PV_NUMERIC))
+               goto parse_failed;
+
+             if (lex_match (lexer, T_LPAREN)
+                 && lex_match_id (lexer, "PAIRED")
+                 && lex_match (lexer, T_RPAREN))
+               {
+                 paired = true;
+                 if (n_v1 != n_v2)
+                   {
+                     msg (SE, _("PAIRED was specified but the number of variables "
+                                "preceding WITH (%zu) did not match the number "
+                                "following (%zu)."),
+                          n_v1, n_v2);
+                     goto parse_failed;
+                   }
+               }
+           }
+         {
+           int i;
+
+           if ( !with )
+             n_pairs = (n_v1 * (n_v1 - 1)) / 2.0;
+           else if ( paired )
+             n_pairs = n_v1;
+           else
+             n_pairs = n_v1 * n_v2;
+         
+           pairs = xcalloc (sizeof *pairs, n_pairs);
+
+
+           if ( with)
+             {
+               int x = 0;
+               if (paired)
+                 {
+                   for (i = 0 ; i < n_v1; ++i)
+                     {
+                       vp *pair = &pairs[i];
+                       (*pair)[0] = v1[i];
+                       (*pair)[1] = v2[i];
+                     } 
+                 }
+               else
+                 {
+                   for (i = 0 ; i < n_v1; ++i)
+                     {
+                       int j;
+                       for (j = 0 ; j < n_v2; ++j)
+                         {
+                           vp *pair = &pairs[x++];
+                           (*pair)[0] = v1[i];
+                           (*pair)[1] = v2[j];
+                         }
+                     }
+                 }
+             }
+           else
+             {
+               int x = 0;
+               for (i = 0 ; i < n_v1; ++i)
+                 {
+                   int j;
+
+                   for (j = i + 1 ; j < n_v1; ++j)
+                     {
+                       vp *pair = &pairs[x++];
+                       (*pair)[0] = v1[i];
+                       (*pair)[1] = v1[j];
+                     }
+                 }
+             }
+
+         }
+       }
+      else if (lex_match_id (lexer, "VARIABLES"))
+       {
+         if ( tt.mode == MODE_PAIRED)
+           {
+             msg (SE, _("VARIABLES subcommand may not be used with PAIRS."));
+             goto parse_failed;
+           }
+
+         lex_match (lexer, T_EQUALS);
+
+         if (!parse_variables_const (lexer, dict,
+                                     &tt.vars,
+                                     &tt.n_vars,
+                                     PV_NO_DUPLICATE | PV_NUMERIC))
+           goto parse_failed;
+       }
+      else if ( lex_match_id (lexer, "MISSING"))
+       {
+          lex_match (lexer, T_EQUALS);
+          while (lex_token (lexer) != T_ENDCMD && lex_token (lexer) != T_SLASH)
+            {
+             if (lex_match_id (lexer, "INCLUDE"))
+               {
+                 tt.exclude = MV_SYSTEM;
+               }
+             else if (lex_match_id (lexer, "EXCLUDE"))
+               {
+                 tt.exclude = MV_ANY;
+               }
+             else if (lex_match_id (lexer, "LISTWISE"))
+               {
+                 tt.missing_type = MISS_LISTWISE;
+               }
+             else if (lex_match_id (lexer, "ANALYSIS"))
+               {
+                 tt.missing_type = MISS_ANALYSIS;
+               }
+             else
+               {
+                  lex_error (lexer, NULL);
+                 goto parse_failed;
+               }
+             lex_match (lexer, T_COMMA);
+           }
+       }
+      else if (lex_match_id (lexer, "CRITERIA"))
+       {
+          lex_match (lexer, T_EQUALS);
+         if ( lex_force_match_id (lexer, "CIN"))
+           if ( lex_force_match (lexer, T_LPAREN))
+             {
+               lex_force_num (lexer);
+               tt.confidence = lex_number (lexer);
+               lex_get (lexer);
+               lex_force_match (lexer, T_RPAREN);
+             }
+       }
+      else 
+       {
+         lex_error (lexer, NULL);
+         goto parse_failed;
+       }
+    }
+
+  if ( mode_count != 1)
+    {
+      msg (SE, _("Exactly one of TESTVAL, GROUPS and PAIRS subcommands "
+                "must be specified."));
+      goto parse_failed;
+    }
+
+  if (tt.n_vars == 0 && tt.mode != MODE_PAIRED)
+    {
+      msg (SE, _("One or more VARIABLES must be specified."));
+      goto parse_failed;
+    }
+
+
+
+  /* Deal with splits etc */
+  {
+    struct casereader *group;
+    struct casegrouper *grouper = casegrouper_create_splits (proc_open (ds), dict);
+
+    while (casegrouper_get_next_group (grouper, &group))
+      {
+       if ( tt.mode == MODE_SINGLE)
+         {
+           if ( tt.missing_type == MISS_LISTWISE )
+             group  = casereader_create_filter_missing (group,
+                                                        tt.vars, tt.n_vars,
+                                                        tt.exclude,
+                                                        NULL,  NULL);
+           one_sample_run (&tt, testval, group);
+         }
+       else if ( tt.mode == MODE_PAIRED)
+         {
+           if ( tt.missing_type == MISS_LISTWISE )
+             {
+               group  = casereader_create_filter_missing (group,
+                                                          v1, n_v1,
+                                                          tt.exclude,
+                                                          NULL,  NULL);
+               group  = casereader_create_filter_missing (group,
+                                                          v2, n_v2,
+                                                          tt.exclude,
+                                                          NULL,  NULL);
+             }
+
+           paired_run (&tt, n_pairs, pairs, group);
+         }
+       else /* tt.mode == MODE_INDEP */
+         {
+           if ( tt.missing_type == MISS_LISTWISE )
+             {
+               group  = casereader_create_filter_missing (group,
+                                                          tt.vars, tt.n_vars,
+                                                          tt.exclude,
+                                                          NULL,  NULL);
+
+               group  = casereader_create_filter_missing (group,
+                                                          &gvar, 1,
+                                                          tt.exclude,
+                                                          NULL,  NULL);
+
+             }
+
+           indep_run (&tt, gvar, cut, &gval0, &gval1, group);
+         }
+      }
+
+    ok = casegrouper_destroy (grouper);
+    ok = proc_commit (ds) && ok;
+  }
+
+  free (pairs);
+  free (v1);
+  free (v2);
+
+  free (tt.vars);
+
+  return ok ? CMD_SUCCESS : CMD_FAILURE;
+
+ parse_failed:
+  return CMD_FAILURE;
+}
+
diff --git a/src/language/stats/t-test.h b/src/language/stats/t-test.h
new file mode 100644 (file)
index 0000000..c2e8099
--- /dev/null
@@ -0,0 +1,62 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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/>. */
+
+#ifndef T_TEST_H
+#define T_TEST_H 1
+
+#include "data/missing-values.h"
+
+struct variable;
+typedef const struct variable *vp[2];
+
+enum missing_type
+  {
+    MISS_LISTWISE,
+    MISS_ANALYSIS,
+  };
+
+enum mode
+  {
+    MODE_undef,
+    MODE_PAIRED,
+    MODE_INDEP,
+    MODE_SINGLE,
+  };
+
+struct tt
+{
+  size_t n_vars;
+  const struct variable **vars;
+  enum mode mode;
+  enum missing_type missing_type;
+  enum mv_class exclude;
+  double confidence;
+  const struct variable *wv;
+  const struct dictionary *dict;
+};
+
+struct casereader;
+union value;
+
+void one_sample_run (const struct tt *tt, double testval, struct casereader *reader);
+void paired_run (const struct tt *tt, size_t n_pairs, vp *pairs, struct casereader *reader);
+void indep_run (struct tt *tt, const struct variable *gvar,
+               bool cut,
+               const union value *gval0, const union value *gval1,
+               struct casereader *reader);
+
+
+#endif
diff --git a/src/language/stats/t-test.q b/src/language/stats/t-test.q
deleted file mode 100644 (file)
index d26fc8a..0000000
+++ /dev/null
@@ -1,1560 +0,0 @@
-/* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2009, 2010, 2011 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 <gsl/gsl_cdf.h>
-#include <math.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "data/case.h"
-#include "data/casegrouper.h"
-#include "data/casereader.h"
-#include "data/dataset.h"
-#include "data/dictionary.h"
-#include "data/format.h"
-#include "data/value-labels.h"
-#include "data/variable.h"
-#include "language/command.h"
-#include "language/dictionary/split-file.h"
-#include "language/lexer/lexer.h"
-#include "language/lexer/value-parser.h"
-#include "libpspp/array.h"
-#include "libpspp/assertion.h"
-#include "libpspp/compiler.h"
-#include "libpspp/hash.h"
-#include "libpspp/message.h"
-#include "libpspp/misc.h"
-#include "libpspp/str.h"
-#include "libpspp/taint.h"
-#include "math/correlation.h"
-#include "math/group-proc.h"
-#include "math/levene.h"
-#include "output/tab.h"
-
-#include "gl/minmax.h"
-#include "gl/xalloc.h"
-#include "gl/xmemdup0.h"
-
-#include "gettext.h"
-#define _(msgid) gettext (msgid)
-
-/* (headers) */
-
-/* (specification)
-   "T-TEST" (tts_):
-   +groups=custom;
-   testval=double;
-   +variables=varlist("PV_NO_SCRATCH | PV_NUMERIC");
-   +pairs=custom;
-   missing=miss:!analysis/listwise,
-   incl:include/!exclude;
-   +format=fmt:!labels/nolabels;
-   criteria=:cin(d:criteria,"%s > 0. && %s < 1.").
-*/
-/* (declarations) */
-/* (functions) */
-
-enum comparison
-  {
-    CMP_LE,
-    CMP_EQ,
-  };
-
-/* A pair of variables to be compared. */
-struct pair
-  {
-    const struct variable *v[2]; /* The paired variables. */
-    double n;             /* The number of valid variable pairs */
-    double sum[2];        /* The sum of the members */
-    double ssq[2];        /* sum of squares of the members */
-    double std_dev[2];    /* Std deviation of the members */
-    double s_std_dev[2];  /* Sample Std deviation of the members */
-    double mean[2];       /* The means of the members */
-    double correlation;   /* Correlation coefficient between the variables. */
-    double sum_of_diffs;  /* The sum of the differences */
-    double sum_of_prod;   /* The sum of the products */
-    double mean_diff;     /* The mean of the differences */
-    double ssq_diffs;     /* The sum of the squares of the differences */
-    double std_dev_diff;  /* The std deviation of the differences */
-  };
-
-/* Which mode was T-TEST invoked */
-enum t_test_mode {
-  T_1_SAMPLE,                   /* One-sample tests. */
-  T_IND_SAMPLES,                /* Independent-sample tests. */
-  T_PAIRED                      /* Paired-sample tests. */
-};
-
-/* Total state of a T-TEST procedure. */
-struct t_test_proc
-  {
-    enum t_test_mode mode;      /* Mode that T-TEST was invoked in. */
-    double criteria;            /* Confidence interval in (0, 1). */
-    enum mv_class exclude;      /* Classes of missing values to exclude. */
-    bool listwise_missing;      /* Drop whole case if one missing var? */
-    struct fmt_spec weight_format; /* Format of weight variable. */
-
-    /* Dependent variables. */
-    const struct variable **vars;
-    size_t n_vars;
-
-    /* For mode == T_1_SAMPLE. */
-    double testval;
-
-    /* For mode == T_PAIRED only. */
-    struct pair *pairs;
-    size_t n_pairs;
-
-    /* For mode == T_IND_SAMPLES only. */
-    struct variable *indep_var; /* Independent variable. */
-    enum comparison criterion;  /* Type of comparison. */
-    double critical_value;      /* CMP_LE only: Grouping threshold value. */
-    union value g_value[2];     /* CMP_EQ only: Per-group indep var values. */
-  };
-
-/* Statistics Summary Box */
-struct ssbox
-  {
-    struct tab_table *t;
-    void (*populate) (struct ssbox *, struct t_test_proc *);
-    void (*finalize) (struct ssbox *);
-  };
-
-static void ssbox_create (struct ssbox *, struct t_test_proc *);
-static void ssbox_populate (struct ssbox *, struct t_test_proc *);
-static void ssbox_finalize (struct ssbox *);
-
-/* Paired Samples Correlation box */
-static void pscbox (struct t_test_proc *);
-
-
-/* Test Results Box. */
-struct trbox {
-  struct tab_table *t;
-  void (*populate) (struct trbox *, struct t_test_proc *);
-  void (*finalize) (struct trbox *);
-  };
-
-static void trbox_create (struct trbox *, struct t_test_proc *);
-static void trbox_populate (struct trbox *, struct t_test_proc *);
-static void trbox_finalize (struct trbox *);
-
-static void calculate (struct t_test_proc *, struct casereader *,
-                       const struct dataset *);
-
-static int compare_group_binary (const struct group_statistics *a,
-                                 const struct group_statistics *b,
-                                 const struct t_test_proc *);
-static unsigned hash_group_binary (const struct group_statistics *g,
-                                  const struct t_test_proc *p);
-
-static void t_test_proc_destroy (struct t_test_proc *proc);
-
-int
-cmd_t_test (struct lexer *lexer, struct dataset *ds)
-{
-  struct cmd_t_test cmd;
-  struct t_test_proc proc;
-  struct casegrouper *grouper;
-  struct casereader *group;
-  struct variable *wv;
-  bool ok = false;
-
-  proc.pairs = NULL;
-  proc.n_pairs = 0;
-  proc.vars = NULL;
-  proc.indep_var = NULL;
-  if (!parse_t_test (lexer, ds, &cmd, &proc))
-    goto parse_failed;
-
-  wv = dict_get_weight (dataset_dict (ds));
-  proc.weight_format = wv ? *var_get_print_format (wv) : F_8_0;
-
-  if ((cmd.sbc_testval != 0) + (cmd.sbc_groups != 0) + (cmd.sbc_pairs != 0)
-      != 1)
-    {
-      msg (SE, _("Exactly one of TESTVAL, GROUPS and PAIRS subcommands "
-                 "must be specified."));
-      goto error;
-    }
-
-  proc.mode = (cmd.sbc_testval ? T_1_SAMPLE
-               : cmd.sbc_groups ? T_IND_SAMPLES
-               : T_PAIRED);
-  proc.criteria = cmd.sbc_criteria ? cmd.criteria : 0.95;
-  proc.exclude = cmd.incl != TTS_INCLUDE ? MV_ANY : MV_SYSTEM;
-  proc.listwise_missing = cmd.miss == TTS_LISTWISE;
-
-  if (proc.mode == T_1_SAMPLE)
-    proc.testval = cmd.n_testval[0];
-
-  if (proc.mode == T_PAIRED)
-    {
-      size_t i, j;
-
-      if (cmd.sbc_variables)
-       {
-         msg (SE, _("VARIABLES subcommand may not be used with PAIRS."));
-          goto error;
-       }
-
-      /* Fill proc.vars with the unique variables from pairs. */
-      proc.n_vars = proc.n_pairs * 2;
-      proc.vars = xmalloc (sizeof *proc.vars * proc.n_vars);
-      for (i = j = 0; i < proc.n_pairs; i++)
-        {
-          proc.vars[j++] = proc.pairs[i].v[0];
-          proc.vars[j++] = proc.pairs[i].v[1];
-        }
-      proc.n_vars = sort_unique (proc.vars, proc.n_vars, sizeof *proc.vars,
-                                 compare_var_ptrs_by_name, NULL);
-    }
-  else
-    {
-      if (!cmd.n_variables)
-        {
-          msg (SE, _("One or more VARIABLES must be specified."));
-          goto error;
-        }
-      proc.n_vars = cmd.n_variables;
-      proc.vars = cmd.v_variables;
-      cmd.v_variables = NULL;
-    }
-
-  /* Data pass. */
-  grouper = casegrouper_create_splits (proc_open (ds), dataset_dict (ds));
-  while (casegrouper_get_next_group (grouper, &group))
-    calculate (&proc, group, ds);
-  ok = casegrouper_destroy (grouper);
-
-  /* Free 'proc' then commit the procedure.  Must happen in this order because
-     if proc->indep_var was created by a temporary transformation then
-     committing will destroy it.  */
-  t_test_proc_destroy (&proc);
-  ok = proc_commit (ds) && ok;
-
-  return ok ? CMD_SUCCESS : CMD_FAILURE;
-
-error:
-  free_t_test (&cmd);
-parse_failed:
-  t_test_proc_destroy (&proc);
-  return CMD_FAILURE;
-}
-
-static void
-t_test_proc_destroy (struct t_test_proc *proc)
-{
-  if (proc->indep_var != NULL)
-    {
-      int width = var_get_width (proc->indep_var);
-      value_destroy (&proc->g_value[0], width);
-      value_destroy (&proc->g_value[1], width);
-    }
-  free (proc->vars);
-  free (proc->pairs);
-}
-
-static int
-tts_custom_groups (struct lexer *lexer, struct dataset *ds,
-                   struct cmd_t_test *cmd UNUSED, void *proc_)
-{
-  struct t_test_proc *proc = proc_;
-  int n_values;
-  int width;
-
-  lex_match (lexer, T_EQUALS);
-
-  proc->indep_var = parse_variable (lexer, dataset_dict (ds));
-  if (proc->indep_var == NULL)
-    {
-      lex_error (lexer, "expecting variable name in GROUPS subcommand");
-      return 0;
-    }
-  width = var_get_width (proc->indep_var);
-  value_init (&proc->g_value[0], width);
-  value_init (&proc->g_value[1], width);
-
-  if (!lex_match (lexer, T_LPAREN))
-    n_values = 0;
-  else
-    {
-      if (!parse_value (lexer, &proc->g_value[0], proc->indep_var))
-        return 0;
-      lex_match (lexer, T_COMMA);
-      if (lex_match (lexer, T_RPAREN))
-        n_values = 1;
-      else
-        {
-          if (!parse_value (lexer, &proc->g_value[1], proc->indep_var)
-              || !lex_force_match (lexer, T_RPAREN))
-            return 0;
-          n_values = 2;
-        }
-    }
-
-  if (var_is_numeric (proc->indep_var))
-    {
-      proc->criterion = n_values == 1 ? CMP_LE : CMP_EQ;
-      if (n_values == 1)
-        proc->critical_value = proc->g_value[0].f;
-      else if (n_values == 0)
-       {
-         proc->g_value[0].f = 1;
-         proc->g_value[1].f = 2;
-       }
-    }
-  else
-    {
-      proc->criterion = CMP_EQ;
-      if (n_values != 2)
-       {
-         msg (SE, _("When applying GROUPS to a string variable, two "
-                     "values must be specified."));
-         return 0;
-       }
-    }
-  return 1;
-}
-
-static void
-add_pair (struct t_test_proc *proc,
-          const struct variable *v0, const struct variable *v1)
-{
-  struct pair *p = &proc->pairs[proc->n_pairs++];
-  p->v[0] = v0;
-  p->v[1] = v1;
-}
-
-static int
-tts_custom_pairs (struct lexer *lexer, struct dataset *ds,
-                  struct cmd_t_test *cmd UNUSED, void *proc_)
-{
-  struct t_test_proc *proc = proc_;
-
-  const struct variable **vars1 = NULL;
-  size_t n_vars1 = 0;
-
-  const struct variable **vars2 = NULL;
-  size_t n_vars2 = 0;
-
-  bool paired = false;
-
-  size_t n_total_pairs;
-  size_t i, j;
-
-  lex_match (lexer, T_EQUALS);
-
-  if (!parse_variables_const (lexer, dataset_dict (ds), &vars1, &n_vars1,
-                              PV_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH))
-    return 0;
-
-  if (lex_match (lexer, T_WITH))
-    {
-      if (!parse_variables_const (lexer, dataset_dict (ds), &vars2, &n_vars2,
-                                  PV_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH))
-        {
-          free (vars1);
-          return 0;
-        }
-
-      if (lex_match (lexer, T_LPAREN)
-          && lex_match_id (lexer, "PAIRED")
-          && lex_match (lexer, T_RPAREN))
-        {
-          paired = true;
-          if (n_vars1 != n_vars2)
-            {
-              msg (SE, _("PAIRED was specified but the number of variables "
-                         "preceding WITH (%zu) did not match the number "
-                         "following (%zu)."),
-                   n_vars1, n_vars2);
-              free (vars1);
-              free (vars2);
-              return 0;
-            }
-        }
-    }
-  else
-    {
-      if (n_vars1 < 2)
-       {
-         free (vars1);
-         msg (SE, _("At least two variables must be specified on PAIRS."));
-         return 0;
-       }
-    }
-
-  /* Allocate storage for the new pairs. */
-  n_total_pairs = proc->n_pairs + (paired ? n_vars1
-                                   : n_vars2 > 0 ? n_vars1 * n_vars2
-                                   : n_vars1 * (n_vars1 - 1) / 2);
-  proc->pairs = xnrealloc (proc->pairs, n_total_pairs, sizeof *proc->pairs);
-
-  /* Populate the pairs with the appropriate variables. */
-  if (paired)
-    for (i = 0; i < n_vars1; i++)
-      add_pair (proc, vars1[i], vars2[i]);
-  else if (n_vars2 > 0)
-    for (i = 0; i < n_vars1; i++)
-      for (j = 0; j < n_vars2; j++)
-        add_pair (proc, vars1[i], vars2[j]);
-  else
-    for (i = 0; i < n_vars1; i++)
-      for (j = i + 1; j < n_vars1; j++)
-        add_pair (proc, vars1[i], vars1[j]);
-  assert (proc->n_pairs == n_total_pairs);
-
-  free (vars1);
-  free (vars2);
-  return 1;
-}
-\f
-/* Implementation of the SSBOX object. */
-
-static void ssbox_base_init (struct ssbox *, int cols, int rows);
-static void ssbox_base_finalize (struct ssbox *);
-static void ssbox_one_sample_init (struct ssbox *, struct t_test_proc *);
-static void ssbox_independent_samples_init (struct ssbox *, struct t_test_proc *);
-static void ssbox_paired_init (struct ssbox *, struct t_test_proc *);
-
-/* Factory to create an ssbox. */
-static void
-ssbox_create (struct ssbox *ssb, struct t_test_proc *proc)
-{
-  switch (proc->mode)
-    {
-    case T_1_SAMPLE:
-      ssbox_one_sample_init (ssb, proc);
-      break;
-    case T_IND_SAMPLES:
-      ssbox_independent_samples_init (ssb, proc);
-      break;
-    case T_PAIRED:
-      ssbox_paired_init (ssb, proc);
-      break;
-    default:
-      NOT_REACHED ();
-    }
-}
-
-/* Despatcher for the populate method */
-static void
-ssbox_populate (struct ssbox *ssb, struct t_test_proc *proc)
-{
-  ssb->populate (ssb, proc);
-}
-
-/* Despatcher for finalize */
-static void
-ssbox_finalize (struct ssbox *ssb)
-{
-  ssb->finalize (ssb);
-}
-
-/* Submit the box and clear up */
-static void
-ssbox_base_finalize (struct ssbox *ssb)
-{
-  tab_submit (ssb->t);
-}
-
-/* Initialize a ssbox struct */
-static void
-ssbox_base_init (struct ssbox *this, int cols, int rows)
-{
-  this->finalize = ssbox_base_finalize;
-  this->t = tab_create (cols, rows);
-
-  tab_headers (this->t, 0, 0, 1, 0);
-  tab_box (this->t, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols - 1, rows - 1);
-  tab_hline (this->t, TAL_2, 0, cols- 1, 1);
-}
-\f
-/* ssbox implementations. */
-
-static void ssbox_one_sample_populate (struct ssbox *, struct t_test_proc *);
-static void ssbox_independent_samples_populate (struct ssbox *,
-                                                struct t_test_proc *);
-static void ssbox_paired_populate (struct ssbox *, struct t_test_proc *);
-
-/* Initialize the one_sample ssbox */
-static void
-ssbox_one_sample_init (struct ssbox *this, struct t_test_proc *proc)
-{
-  const int hsize = 5;
-  const int vsize = proc->n_vars + 1;
-
-  this->populate = ssbox_one_sample_populate;
-
-  ssbox_base_init (this, hsize, vsize);
-  tab_title (this->t, _("One-Sample Statistics"));
-  tab_vline (this->t, TAL_2, 1, 0, vsize - 1);
-  tab_text (this->t, 1, 0, TAB_CENTER | TAT_TITLE, _("N"));
-  tab_text (this->t, 2, 0, TAB_CENTER | TAT_TITLE, _("Mean"));
-  tab_text (this->t, 3, 0, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
-  tab_text (this->t, 4, 0, TAB_CENTER | TAT_TITLE, _("S.E. Mean"));
-}
-
-/* Initialize the independent samples ssbox */
-static void
-ssbox_independent_samples_init (struct ssbox *this, struct t_test_proc *proc)
-{
-  int hsize=6;
-  int vsize = proc->n_vars * 2 + 1;
-
-  this->populate = ssbox_independent_samples_populate;
-
-  ssbox_base_init (this, hsize, vsize);
-  tab_vline (this->t, TAL_GAP, 1, 0, vsize - 1);
-  tab_title (this->t, _("Group Statistics"));
-  tab_text (this->t, 1, 0, TAB_CENTER | TAT_TITLE,
-            var_get_name (proc->indep_var));
-  tab_text (this->t, 2, 0, TAB_CENTER | TAT_TITLE, _("N"));
-  tab_text (this->t, 3, 0, TAB_CENTER | TAT_TITLE, _("Mean"));
-  tab_text (this->t, 4, 0, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
-  tab_text (this->t, 5, 0, TAB_CENTER | TAT_TITLE, _("S.E. Mean"));
-}
-
-/* Populate the ssbox for independent samples */
-static void
-ssbox_independent_samples_populate (struct ssbox *ssb,
-                                    struct t_test_proc *proc)
-{
-  int i;
-
-  char *val_lab[2];
-  double indep_value[2];
-
-  char prefix[2][3];
-
-  for (i = 0; i < 2; i++)
-    {
-      union value *value = &proc->g_value[i];
-      int width = var_get_width (proc->indep_var);
-
-      indep_value[i] = (proc->criterion == CMP_LE ? proc->critical_value
-                        : value->f);
-
-      if (val_type_from_width (width) == VAL_NUMERIC)
-        {
-          const char *s = var_lookup_value_label (proc->indep_var, value);
-          val_lab[i] = s ? xstrdup (s) : xasprintf ("%g", indep_value[i]);
-        }
-      else
-        val_lab[i] = xmemdup0 (value_str (value, width), width);
-    }
-
-  if (proc->criterion == CMP_LE)
-    {
-      strcpy (prefix[0], ">=");
-      strcpy (prefix[1], "<");
-    }
-  else
-    {
-      strcpy (prefix[0], "");
-      strcpy (prefix[1], "");
-    }
-
-  for (i = 0; i < proc->n_vars; i++)
-    {
-      const struct variable *var = proc->vars[i];
-      struct hsh_table *grp_hash = group_proc_get (var)->group_hash;
-      int count=0;
-
-      tab_text (ssb->t, 0, i * 2 + 1, TAB_LEFT,
-                var_get_name (proc->vars[i]));
-      tab_text_format (ssb->t, 1, i * 2 + 1, TAB_LEFT,
-                       "%s%s", prefix[0], val_lab[0]);
-      tab_text_format (ssb->t, 1, i * 2 + 1+ 1, TAB_LEFT,
-                       "%s%s", prefix[1], val_lab[1]);
-
-      /* Fill in the group statistics */
-      for (count = 0; count < 2; count++)
-       {
-         union value search_val;
-         struct group_statistics *gs;
-
-         if (proc->criterion == CMP_LE)
-            search_val.f = proc->critical_value + (count == 0 ? 1.0 : -1.0);
-         else
-            search_val = proc->g_value[count];
-
-         gs = hsh_find (grp_hash, &search_val);
-         assert (gs);
-
-         tab_double (ssb->t, 2, i * 2 + count+ 1, TAB_RIGHT, gs->n,
-                      &proc->weight_format);
-         tab_double (ssb->t, 3, i * 2 + count+ 1, TAB_RIGHT, gs->mean, NULL);
-         tab_double (ssb->t, 4, i * 2 + count+ 1, TAB_RIGHT, gs->std_dev,
-                      NULL);
-         tab_double (ssb->t, 5, i * 2 + count+ 1, TAB_RIGHT, gs->se_mean,
-                      NULL);
-       }
-    }
-  free (val_lab[0]);
-  free (val_lab[1]);
-}
-
-/* Initialize the paired values ssbox */
-static void
-ssbox_paired_init (struct ssbox *this, struct t_test_proc *proc)
-{
-  int hsize = 6;
-  int vsize = proc->n_pairs * 2 + 1;
-
-  this->populate = ssbox_paired_populate;
-
-  ssbox_base_init (this, hsize, vsize);
-  tab_title (this->t, _("Paired Sample Statistics"));
-  tab_vline (this->t, TAL_GAP, 1, 0, vsize - 1);
-  tab_vline (this->t, TAL_2, 2, 0, vsize - 1);
-  tab_text (this->t, 2, 0, TAB_CENTER | TAT_TITLE, _("Mean"));
-  tab_text (this->t, 3, 0, TAB_CENTER | TAT_TITLE, _("N"));
-  tab_text (this->t, 4, 0, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
-  tab_text (this->t, 5, 0, TAB_CENTER | TAT_TITLE, _("S.E. Mean"));
-}
-
-/* Populate the ssbox for paired values */
-static void
-ssbox_paired_populate (struct ssbox *ssb, struct t_test_proc *proc)
-{
-  int i;
-
-  for (i = 0; i < proc->n_pairs; i++)
-    {
-      struct pair *p = &proc->pairs[i];
-      int j;
-
-      tab_text_format (ssb->t, 0, i * 2 + 1, TAB_LEFT, _("Pair %d"), i);
-      for (j=0; j < 2; j++)
-       {
-         /* Titles */
-         tab_text (ssb->t, 1, i * 2 + j + 1, TAB_LEFT,
-                    var_get_name (p->v[j]));
-
-         /* Values */
-         tab_double (ssb->t, 2, i * 2 + j + 1, TAB_RIGHT, p->mean[j], NULL);
-         tab_double (ssb->t, 3, i * 2 + j + 1, TAB_RIGHT, p->n,
-                      &proc->weight_format);
-         tab_double (ssb->t, 4, i * 2 + j + 1, TAB_RIGHT, p->std_dev[j],
-                      NULL);
-         tab_double (ssb->t, 5, i * 2 + j + 1, TAB_RIGHT,
-                     p->std_dev[j] /sqrt (p->n), NULL);
-       }
-    }
-}
-
-/* Populate the one sample ssbox */
-static void
-ssbox_one_sample_populate (struct ssbox *ssb, struct t_test_proc *proc)
-{
-  int i;
-
-  for (i = 0; i < proc->n_vars; i++)
-    {
-      struct group_statistics *gs = &group_proc_get (proc->vars[i])->ugs;
-
-      tab_text (ssb->t, 0, i + 1, TAB_LEFT, var_get_name (proc->vars[i]));
-      tab_double (ssb->t, 1, i + 1, TAB_RIGHT, gs->n, &proc->weight_format);
-      tab_double (ssb->t, 2, i + 1, TAB_RIGHT, gs->mean, NULL);
-      tab_double (ssb->t, 3, i + 1, TAB_RIGHT, gs->std_dev, NULL);
-      tab_double (ssb->t, 4, i + 1, TAB_RIGHT, gs->se_mean, NULL);
-    }
-}
-\f
-/* Implementation of the Test Results box struct */
-
-static void trbox_base_init (struct trbox *, size_t n_vars, int cols);
-static void trbox_base_finalize (struct trbox *);
-static void trbox_independent_samples_init (struct trbox *,
-                                            struct t_test_proc *);
-static void trbox_independent_samples_populate (struct trbox *,
-                                                struct t_test_proc *);
-static void trbox_one_sample_init (struct trbox *, struct t_test_proc *);
-static void trbox_one_sample_populate (struct trbox *, struct t_test_proc *);
-static void trbox_paired_init (struct trbox *, struct t_test_proc *);
-static void trbox_paired_populate (struct trbox *, struct t_test_proc *);
-
-/* Create a trbox according to mode*/
-static void
-trbox_create (struct trbox *trb, struct t_test_proc *proc)
-{
-  switch (proc->mode)
-    {
-    case T_1_SAMPLE:
-      trbox_one_sample_init (trb, proc);
-      break;
-    case T_IND_SAMPLES:
-      trbox_independent_samples_init (trb, proc);
-      break;
-    case T_PAIRED:
-      trbox_paired_init (trb, proc);
-      break;
-    default:
-      NOT_REACHED ();
-    }
-}
-
-/* Populate a trbox according to proc */
-static void
-trbox_populate (struct trbox *trb, struct t_test_proc *proc)
-{
-  trb->populate (trb, proc);
-}
-
-/* Submit and destroy a trbox */
-static void
-trbox_finalize (struct trbox *trb)
-{
-  trb->finalize (trb);
-}
-
-/* Initialize the independent samples trbox */
-static void
-trbox_independent_samples_init (struct trbox *self,
-                                struct t_test_proc *proc)
-{
-  const int hsize = 11;
-  const int vsize = proc->n_vars * 2 + 3;
-
-  assert (self);
-  self->populate = trbox_independent_samples_populate;
-
-  trbox_base_init (self, proc->n_vars * 2, hsize);
-  tab_title (self->t, _("Independent Samples Test"));
-  tab_hline (self->t, TAL_1, 2, hsize - 1, 1);
-  tab_vline (self->t, TAL_2, 2, 0, vsize - 1);
-  tab_vline (self->t, TAL_1, 4, 0, vsize - 1);
-  tab_box (self->t, -1, -1, -1, TAL_1, 2, 1, hsize - 2, vsize - 1);
-  tab_hline (self->t, TAL_1, hsize - 2, hsize - 1, 2);
-  tab_box (self->t, -1, -1, -1, TAL_1, hsize - 2, 2, hsize - 1, vsize - 1);
-  tab_joint_text (self->t, 2, 0, 3, 0,
-                  TAB_CENTER, _("Levene's Test for Equality of Variances"));
-  tab_joint_text (self->t, 4, 0, hsize- 1, 0,
-                  TAB_CENTER, _("t-test for Equality of Means"));
-
-  tab_text (self->t, 2, 2, TAB_CENTER | TAT_TITLE, _("F"));
-  tab_text (self->t, 3, 2, TAB_CENTER | TAT_TITLE, _("Sig."));
-  tab_text (self->t, 4, 2, TAB_CENTER | TAT_TITLE, _("t"));
-  tab_text (self->t, 5, 2, TAB_CENTER | TAT_TITLE, _("df"));
-  tab_text (self->t, 6, 2, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
-  tab_text (self->t, 7, 2, TAB_CENTER | TAT_TITLE, _("Mean Difference"));
-  tab_text (self->t, 8, 2, TAB_CENTER | TAT_TITLE, _("Std. Error Difference"));
-  tab_text (self->t, 9, 2, TAB_CENTER | TAT_TITLE, _("Lower"));
-  tab_text (self->t, 10, 2, TAB_CENTER | TAT_TITLE, _("Upper"));
-
-  tab_joint_text_format (self->t, 9, 1, 10, 1, TAB_CENTER,
-                         _("%g%% Confidence Interval of the Difference"),
-                         proc->criteria * 100.0);
-}
-
-/* Populate the independent samples trbox */
-static void
-trbox_independent_samples_populate (struct trbox *self,
-                                    struct t_test_proc *proc)
-{
-  int i;
-
-  for (i = 0; i < proc->n_vars; i++)
-    {
-      double p, q;
-
-      double t;
-      double df;
-
-      double df1, df2;
-
-      double pooled_variance;
-      double std_err_diff;
-      double mean_diff;
-
-      double se2;
-
-      const struct variable *var = proc->vars[i];
-      struct group_proc *grp_data = group_proc_get (var);
-
-      struct hsh_table *grp_hash = grp_data->group_hash;
-
-      struct group_statistics *gs0;
-      struct group_statistics *gs1;
-
-      union value search_val;
-
-      if (proc->criterion == CMP_LE)
-       search_val.f = proc->critical_value - 1.0;
-      else
-       search_val = proc->g_value[0];
-
-      gs0 = hsh_find (grp_hash, &search_val);
-      assert (gs0);
-
-      if (proc->criterion == CMP_LE)
-       search_val.f = proc->critical_value + 1.0;
-      else
-       search_val = proc->g_value[1];
-
-      gs1 = hsh_find (grp_hash, &search_val);
-      assert (gs1);
-
-
-      tab_text (self->t, 0, i * 2 + 3, TAB_LEFT, var_get_name (proc->vars[i]));
-      tab_text (self->t, 1, i * 2 + 3, TAB_LEFT, _("Equal variances assumed"));
-      tab_double (self->t, 2, i * 2 + 3, TAB_CENTER, grp_data->levene, NULL);
-
-      /* Now work out the significance of the Levene test */
-      df1 = 1;
-      df2 = grp_data->ugs.n - 2;
-      q = gsl_cdf_fdist_Q (grp_data->levene, df1, df2);
-      tab_double (self->t, 3, i * 2 + 3, TAB_CENTER, q, NULL);
-
-      df = gs0->n + gs1->n - 2.0;
-      tab_double (self->t, 5, i * 2 + 3, TAB_RIGHT, df, NULL);
-
-      pooled_variance = (gs0->n * pow2 (gs0->s_std_dev)
-                         + gs1->n *pow2 (gs1->s_std_dev)) / df ;
-
-      t = (gs0->mean - gs1->mean) / sqrt (pooled_variance);
-      t /= sqrt ((gs0->n + gs1->n) / (gs0->n * gs1->n));
-
-      tab_double (self->t, 4, i * 2 + 3, TAB_RIGHT, t, NULL);
-
-      p = gsl_cdf_tdist_P (t, df);
-      q = gsl_cdf_tdist_Q (t, df);
-
-      tab_double (self->t, 6, i * 2 + 3, TAB_RIGHT, 2.0 * (t > 0 ? q : p),
-                  NULL);
-
-      mean_diff = gs0->mean - gs1->mean;
-      tab_double (self->t, 7, i * 2 + 3, TAB_RIGHT, mean_diff, NULL);
-
-
-      std_err_diff = sqrt (pow2 (gs0->se_mean) + pow2 (gs1->se_mean));
-      tab_double (self->t, 8, i * 2 + 3, TAB_RIGHT, std_err_diff, NULL);
-
-      /* Now work out the confidence interval */
-      q = (1 - proc->criteria)/2.0;  /* 2-tailed test */
-
-      t = gsl_cdf_tdist_Qinv (q, df);
-      tab_double (self->t, 9, i * 2 + 3, TAB_RIGHT,
-                 mean_diff - t * std_err_diff, NULL);
-
-      tab_double (self->t, 10, i * 2 + 3, TAB_RIGHT,
-                 mean_diff + t * std_err_diff, NULL);
-
-
-      /* Now for the \sigma_1 != \sigma_2 case */
-      tab_text (self->t, 1, i * 2 + 3 + 1,
-                TAB_LEFT, _("Equal variances not assumed"));
-
-      se2 = ((pow2 (gs0->s_std_dev) / (gs0->n - 1)) +
-             (pow2 (gs1->s_std_dev) / (gs1->n - 1)));
-
-      t = mean_diff / sqrt (se2);
-      tab_double (self->t, 4, i * 2 + 3 + 1, TAB_RIGHT, t, NULL);
-
-      df = pow2 (se2) / ((pow2 (pow2 (gs0->s_std_dev) / (gs0->n - 1))
-                          / (gs0->n - 1))
-                         + (pow2 (pow2 (gs1->s_std_dev) / (gs1->n - 1))
-                            / (gs1->n - 1)));
-      tab_double (self->t, 5, i * 2 + 3 + 1, TAB_RIGHT, df, NULL);
-
-      p = gsl_cdf_tdist_P (t, df);
-      q = gsl_cdf_tdist_Q (t, df);
-
-      tab_double (self->t, 6, i * 2 + 3 + 1, TAB_RIGHT, 2.0 * (t > 0 ? q : p),
-                  NULL);
-
-      /* Now work out the confidence interval */
-      q = (1 - proc->criteria) / 2.0;  /* 2-tailed test */
-
-      t = gsl_cdf_tdist_Qinv (q, df);
-
-      tab_double (self->t, 7, i * 2 + 3 + 1, TAB_RIGHT, mean_diff, NULL);
-      tab_double (self->t, 8, i * 2 + 3 + 1, TAB_RIGHT, std_err_diff, NULL);
-      tab_double (self->t, 9, i * 2 + 3 + 1, TAB_RIGHT,
-                 mean_diff - t * std_err_diff, NULL);
-      tab_double (self->t, 10, i * 2 + 3 + 1, TAB_RIGHT,
-                 mean_diff + t * std_err_diff, NULL);
-    }
-}
-
-/* Initialize the paired samples trbox */
-static void
-trbox_paired_init (struct trbox *self, struct t_test_proc *proc)
-{
-  const int hsize=10;
-  const int vsize=proc->n_pairs+ 3;
-
-  self->populate = trbox_paired_populate;
-
-  trbox_base_init (self, proc->n_pairs, hsize);
-  tab_title (self->t, _("Paired Samples Test"));
-  tab_hline (self->t, TAL_1, 2, 6, 1);
-  tab_vline (self->t, TAL_2, 2, 0, vsize - 1);
-  tab_joint_text (self->t, 2, 0, 6, 0, TAB_CENTER, _("Paired Differences"));
-  tab_box (self->t, -1, -1, -1, TAL_1, 2, 1, 6, vsize - 1);
-  tab_box (self->t, -1, -1, -1, TAL_1, 6, 0, hsize - 1, vsize - 1);
-  tab_hline (self->t, TAL_1, 5, 6, 2);
-  tab_vline (self->t, TAL_GAP, 6, 0, 1);
-
-  tab_joint_text_format (self->t, 5, 1, 6, 1, TAB_CENTER,
-                         _("%g%% Confidence Interval of the Difference"),
-                         proc->criteria*100.0);
-
-  tab_text (self->t, 2, 2, TAB_CENTER | TAT_TITLE, _("Mean"));
-  tab_text (self->t, 3, 2, TAB_CENTER | TAT_TITLE, _("Std. Deviation"));
-  tab_text (self->t, 4, 2, TAB_CENTER | TAT_TITLE, _("Std. Error Mean"));
-  tab_text (self->t, 5, 2, TAB_CENTER | TAT_TITLE, _("Lower"));
-  tab_text (self->t, 6, 2, TAB_CENTER | TAT_TITLE, _("Upper"));
-  tab_text (self->t, 7, 2, TAB_CENTER | TAT_TITLE, _("t"));
-  tab_text (self->t, 8, 2, TAB_CENTER | TAT_TITLE, _("df"));
-  tab_text (self->t, 9, 2, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
-}
-
-/* Populate the paired samples trbox */
-static void
-trbox_paired_populate (struct trbox *trb,
-                       struct t_test_proc *proc)
-{
-  int i;
-
-  for (i = 0; i < proc->n_pairs; i++)
-    {
-      struct pair *pair = &proc->pairs[i];
-      double p, q;
-      double se_mean;
-
-      double n = pair->n;
-      double t;
-      double df = n - 1;
-
-      tab_text_format (trb->t, 0, i + 3, TAB_LEFT, _("Pair %d"), i);
-      tab_text_format (trb->t, 1, i + 3, TAB_LEFT, "%s - %s",
-                       var_get_name (pair->v[0]),
-                       var_get_name (pair->v[1]));
-      tab_double (trb->t, 2, i + 3, TAB_RIGHT, pair->mean_diff, NULL);
-      tab_double (trb->t, 3, i + 3, TAB_RIGHT, pair->std_dev_diff, NULL);
-
-      /* SE Mean */
-      se_mean = pair->std_dev_diff / sqrt (n);
-      tab_double (trb->t, 4, i + 3, TAB_RIGHT, se_mean, NULL);
-
-      /* Now work out the confidence interval */
-      q = (1 - proc->criteria) / 2.0;  /* 2-tailed test */
-
-      t = gsl_cdf_tdist_Qinv (q, df);
-
-      tab_double (trb->t, 5, i + 3, TAB_RIGHT,
-                 pair->mean_diff - t * se_mean, NULL);
-      tab_double (trb->t, 6, i + 3, TAB_RIGHT,
-                 pair->mean_diff + t * se_mean, NULL);
-
-      t = ((pair->mean[0] - pair->mean[1])
-           / sqrt ((pow2 (pair->s_std_dev[0]) + pow2 (pair->s_std_dev[1])
-                    - (2 * pair->correlation
-                       * pair->s_std_dev[0] * pair->s_std_dev[1]))
-                   / (n - 1)));
-
-      tab_double (trb->t, 7, i + 3, TAB_RIGHT, t, NULL);
-
-      /* Degrees of freedom */
-      tab_double (trb->t, 8, i + 3, TAB_RIGHT, df, &proc->weight_format);
-
-      p = gsl_cdf_tdist_P (t,df);
-      q = gsl_cdf_tdist_Q (t,df);
-
-      tab_double (trb->t, 9, i + 3, TAB_RIGHT, 2.0 * (t > 0 ? q : p), NULL);
-    }
-}
-
-/* Initialize the one sample trbox */
-static void
-trbox_one_sample_init (struct trbox *self, struct t_test_proc *proc)
-{
-  const int hsize = 7;
-  const int vsize = proc->n_vars + 3;
-
-  self->populate = trbox_one_sample_populate;
-
-  trbox_base_init (self, proc->n_vars, hsize);
-  tab_title (self->t, _("One-Sample Test"));
-  tab_hline (self->t, TAL_1, 1, hsize - 1, 1);
-  tab_vline (self->t, TAL_2, 1, 0, vsize - 1);
-
-  tab_joint_text_format (self->t, 1, 0, hsize - 1, 0, TAB_CENTER,
-                         _("Test Value = %f"), proc->testval);
-
-  tab_box (self->t, -1, -1, -1, TAL_1, 1, 1, hsize - 1, vsize - 1);
-
-
-  tab_joint_text_format (self->t, 5, 1, 6, 1, TAB_CENTER,
-                         _("%g%% Confidence Interval of the Difference"),
-                         proc->criteria * 100.0);
-
-  tab_vline (self->t, TAL_GAP, 6, 1, 1);
-  tab_hline (self->t, TAL_1, 5, 6, 2);
-  tab_text (self->t, 1, 2, TAB_CENTER | TAT_TITLE, _("t"));
-  tab_text (self->t, 2, 2, TAB_CENTER | TAT_TITLE, _("df"));
-  tab_text (self->t, 3, 2, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)"));
-  tab_text (self->t, 4, 2, TAB_CENTER | TAT_TITLE, _("Mean Difference"));
-  tab_text (self->t, 5, 2, TAB_CENTER | TAT_TITLE, _("Lower"));
-  tab_text (self->t, 6, 2, TAB_CENTER | TAT_TITLE, _("Upper"));
-}
-
-/* Populate the one sample trbox */
-static void
-trbox_one_sample_populate (struct trbox *trb, struct t_test_proc *proc)
-{
-  int i;
-
-  assert (trb->t);
-
-  for (i = 0; i < proc->n_vars; i++)
-    {
-      double t;
-      double p, q;
-      double df;
-      struct group_statistics *gs = &group_proc_get (proc->vars[i])->ugs;
-
-      tab_text (trb->t, 0, i + 3, TAB_LEFT, var_get_name (proc->vars[i]));
-
-      t = (gs->mean - proc->testval) * sqrt (gs->n) / gs->std_dev;
-
-      tab_double (trb->t, 1, i + 3, TAB_RIGHT, t, NULL);
-
-      /* degrees of freedom */
-      df = gs->n - 1;
-
-      tab_double (trb->t, 2, i + 3, TAB_RIGHT, df, &proc->weight_format);
-
-      p = gsl_cdf_tdist_P (t, df);
-      q = gsl_cdf_tdist_Q (t, df);
-
-      /* Multiply by 2 to get 2-tailed significance, makeing sure we've got
-        the correct tail*/
-      tab_double (trb->t, 3, i + 3, TAB_RIGHT, 2.0 * (t > 0 ? q : p), NULL);
-      tab_double (trb->t, 4, i + 3, TAB_RIGHT, gs->mean_diff, NULL);
-
-
-      q = (1 - proc->criteria) / 2.0;  /* 2-tailed test */
-      t = gsl_cdf_tdist_Qinv (q, df);
-
-      tab_double (trb->t, 5, i + 3, TAB_RIGHT,
-                gs->mean_diff - t * gs->se_mean, NULL);
-      tab_double (trb->t, 6, i + 3, TAB_RIGHT,
-                gs->mean_diff + t * gs->se_mean, NULL);
-    }
-}
-
-/* Base initializer for the generalized trbox */
-static void
-trbox_base_init (struct trbox *self, size_t data_rows, int cols)
-{
-  const size_t rows = 3 + data_rows;
-
-  self->finalize = trbox_base_finalize;
-  self->t = tab_create (cols, rows);
-  tab_headers (self->t, 0, 0, 3, 0);
-  tab_box (self->t, TAL_2, TAL_2, TAL_0, TAL_0, 0, 0, cols - 1, rows - 1);
-  tab_hline (self->t, TAL_2, 0, cols- 1, 3);
-}
-
-/* Base finalizer for the trbox */
-static void
-trbox_base_finalize (struct trbox *trb)
-{
-  tab_submit (trb->t);
-}
-
-/* Create, populate and submit the Paired Samples Correlation box */
-static void
-pscbox (struct t_test_proc *proc)
-{
-  const int rows=1+proc->n_pairs;
-  const int cols=5;
-  int i;
-
-  struct tab_table *table;
-
-  table = tab_create (cols, rows);
-
-  tab_headers (table, 0, 0, 1, 0);
-  tab_box (table, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols - 1, rows - 1);
-  tab_hline (table, TAL_2, 0, cols - 1, 1);
-  tab_vline (table, TAL_2, 2, 0, rows - 1);
-  tab_title (table, _("Paired Samples Correlations"));
-
-  /* column headings */
-  tab_text (table, 2, 0, TAB_CENTER | TAT_TITLE, _("N"));
-  tab_text (table, 3, 0, TAB_CENTER | TAT_TITLE, _("Correlation"));
-  tab_text (table, 4, 0, TAB_CENTER | TAT_TITLE, _("Sig."));
-
-  for (i = 0; i < proc->n_pairs; i++)
-    {
-      struct pair *pair = &proc->pairs[i];
-
-      /* row headings */
-      tab_text_format (table, 0, i + 1, TAB_LEFT | TAT_TITLE,
-                       _("Pair %d"), i);
-      tab_text_format (table, 1, i + 1, TAB_LEFT | TAT_TITLE,
-                       _("%s & %s"),
-                       var_get_name (pair->v[0]),
-                       var_get_name (pair->v[1]));
-
-      /* row data */
-      tab_double (table, 2, i + 1, TAB_RIGHT, pair->n, &proc->weight_format);
-      tab_double (table, 3, i + 1, TAB_RIGHT, pair->correlation, NULL);
-
-      tab_double (table, 4, i + 1, TAB_RIGHT, 
-                 2.0 * significance_of_correlation (pair->correlation, pair->n), NULL);
-    }
-
-  tab_submit (table);
-}
-\f
-/* Calculation Implementation */
-
-/* Calculations common to all variants of the T test. */
-static void
-common_calc (const struct dictionary *dict,
-             struct t_test_proc *proc,
-             struct casereader *reader)
-{
-  struct ccase *c;
-  int i;
-
-  for (i = 0; i < proc->n_vars; i++)
-    {
-      struct group_statistics *gs = &group_proc_get (proc->vars[i])->ugs;
-      gs->sum = 0;
-      gs->n = 0;
-      gs->ssq = 0;
-      gs->sum_diff = 0;
-    }
-
-  for (; (c = casereader_read (reader)) != NULL; case_unref (c))
-    {
-      double weight = dict_get_case_weight (dict, c, NULL);
-
-      /* Listwise has to be implicit if the independent variable
-         is missing ?? */
-      if (proc->mode == T_IND_SAMPLES)
-        {
-          if (var_is_value_missing (proc->indep_var,
-                                    case_data (c, proc->indep_var),
-                                    proc->exclude))
-            continue;
-        }
-
-      for (i = 0; i < proc->n_vars; i++)
-        {
-          const struct variable *v = proc->vars[i];
-          const union value *val = case_data (c, v);
-
-          if (!var_is_value_missing (v, val, proc->exclude))
-            {
-              struct group_statistics *gs;
-              gs = &group_proc_get (v)->ugs;
-
-              gs->n += weight;
-              gs->sum += weight * val->f;
-              gs->ssq += weight * pow2 (val->f);
-            }
-        }
-    }
-  casereader_destroy (reader);
-
-  for (i = 0; i < proc->n_vars; i++)
-    {
-      struct group_statistics *gs = &group_proc_get (proc->vars[i])->ugs;
-
-      gs->mean = gs->sum / gs->n;
-      gs->s_std_dev = sqrt (((gs->ssq / gs->n) - pow2 (gs->mean)));
-      gs->std_dev = sqrt (gs->n / (gs->n- 1)
-                          * ((gs->ssq / gs->n) - pow2 (gs->mean)));
-      gs->se_mean = gs->std_dev / sqrt (gs->n);
-      gs->mean_diff = gs->sum_diff / gs->n;
-    }
-}
-
-/* Calculations for one sample T test. */
-static int
-one_sample_calc (const struct dictionary *dict, struct t_test_proc *proc,
-                 struct casereader *reader)
-{
-  struct ccase *c;
-  int i;
-
-  for (i = 0; i < proc->n_vars; i++)
-    {
-      struct group_statistics *gs = &group_proc_get (proc->vars[i])->ugs;
-      gs->sum_diff = 0;
-    }
-
-  for (; (c = casereader_read (reader)) != NULL; case_unref (c))
-    {
-      double weight = dict_get_case_weight (dict, c, NULL);
-      for (i = 0; i < proc->n_vars; i++)
-        {
-          const struct variable *v = proc->vars[i];
-          struct group_statistics *gs = &group_proc_get (v)->ugs;
-          const union value *val = case_data (c, v);
-          if (!var_is_value_missing (v, val, proc->exclude))
-            gs->sum_diff += weight * (val->f - proc->testval);
-        }
-    }
-
-  for (i = 0; i < proc->n_vars; i++)
-    {
-      struct group_statistics *gs = &group_proc_get (proc->vars[i])->ugs;
-      gs->mean_diff = gs->sum_diff / gs->n;
-    }
-
-  casereader_destroy (reader);
-
-  return 0;
-}
-
-static int
-paired_calc (const struct dictionary *dict, struct t_test_proc *proc,
-             struct casereader *reader)
-{
-  struct ccase *c;
-  int i;
-
-  for (i = 0; i < proc->n_pairs; i++)
-    {
-      struct pair *pair = &proc->pairs[i];
-      pair->n = 0;
-      pair->sum[0] = pair->sum[1] = 0;
-      pair->ssq[0] = pair->ssq[1] = 0;
-      pair->sum_of_prod = 0;
-      pair->correlation = 0;
-      pair->sum_of_diffs = 0;
-      pair->ssq_diffs = 0;
-    }
-
-  for (; (c = casereader_read (reader)) != NULL; case_unref (c))
-    {
-      double weight = dict_get_case_weight (dict, c, NULL);
-      for (i = 0; i < proc->n_pairs; i++)
-        {
-          struct pair *pair = &proc->pairs[i];
-          const struct variable *v0 = pair->v[0];
-          const struct variable *v1 = pair->v[1];
-
-          const union value *val0 = case_data (c, v0);
-          const union value *val1 = case_data (c, v1);
-
-          if (!var_is_value_missing (v0, val0, proc->exclude)
-              && !var_is_value_missing (v1, val1, proc->exclude))
-            {
-              pair->n += weight;
-              pair->sum[0] += weight * val0->f;
-              pair->sum[1] += weight * val1->f;
-              pair->ssq[0] += weight * pow2 (val0->f);
-              pair->ssq[1] += weight * pow2 (val1->f);
-              pair->sum_of_prod += weight * val0->f * val1->f;
-              pair->sum_of_diffs += weight * (val0->f - val1->f);
-              pair->ssq_diffs += weight * pow2 (val0->f - val1->f);
-            }
-        }
-    }
-
-  for (i = 0; i < proc->n_pairs; i++)
-    {
-      struct pair *pair = &proc->pairs[i];
-      const double n = pair->n;
-      int j;
-
-      for (j=0; j < 2; j++)
-       {
-         pair->mean[j] = pair->sum[j] / n;
-         pair->s_std_dev[j] = sqrt ((pair->ssq[j] / n
-                                      - pow2 (pair->mean[j])));
-         pair->std_dev[j] = sqrt (n / (n- 1) * (pair->ssq[j] / n
-                                                - pow2 (pair->mean[j])));
-       }
-
-      pair->correlation = (pair->sum_of_prod / pair->n
-                           - pair->mean[0] * pair->mean[1]);
-      /* correlation now actually contains the covariance */
-      pair->correlation /= pair->std_dev[0] * pair->std_dev[1];
-      pair->correlation *= pair->n / (pair->n - 1);
-
-      pair->mean_diff = pair->sum_of_diffs / n;
-      pair->std_dev_diff = sqrt (n / (n - 1) * ((pair->ssq_diffs / n)
-                                                - pow2 (pair->mean_diff)));
-    }
-
-  casereader_destroy (reader);
-  return 0;
-}
-
-static int
-group_calc (const struct dictionary *dict, struct t_test_proc *proc,
-            struct casereader *reader)
-{
-  struct ccase *c;
-  int i;
-
-  for (i = 0; i < proc->n_vars; i++)
-    {
-      struct group_proc *ttpr = group_proc_get (proc->vars[i]);
-      int j;
-
-      /* There's always 2 groups for a T - TEST */
-      ttpr->n_groups = 2;
-      ttpr->group_hash = hsh_create (2,
-                                     (hsh_compare_func *) compare_group_binary,
-                                     (hsh_hash_func *) hash_group_binary,
-                                     (hsh_free_func *) free_group,
-                                     proc);
-
-      for (j = 0; j < 2; j++)
-       {
-         struct group_statistics *gs = xmalloc (sizeof *gs);
-         gs->sum = 0;
-         gs->n = 0;
-         gs->ssq = 0;
-         if (proc->criterion == CMP_EQ)
-            gs->id = proc->g_value[j];
-         else
-           {
-             if (j == 0)
-               gs->id.f = proc->critical_value - 1.0;
-             else
-               gs->id.f = proc->critical_value + 1.0;
-           }
-
-         hsh_insert (ttpr->group_hash, gs);
-       }
-    }
-
-  for (; (c = casereader_read (reader)) != NULL; case_unref (c))
-    {
-      const double weight = dict_get_case_weight (dict, c, NULL);
-      const union value *gv;
-
-      if (var_is_value_missing (proc->indep_var,
-                                case_data (c, proc->indep_var), proc->exclude))
-        continue;
-
-      gv = case_data (c, proc->indep_var);
-      for (i = 0; i < proc->n_vars; i++)
-        {
-          const struct variable *var = proc->vars[i];
-          const union value *val = case_data (c, var);
-          struct hsh_table *grp_hash = group_proc_get (var)->group_hash;
-          struct group_statistics *gs = hsh_find (grp_hash, gv);
-
-          /* If the independent variable doesn't match either of the values
-             for this case then move on to the next case. */
-          if (gs == NULL)
-            break;
-
-          if (!var_is_value_missing (var, val, proc->exclude))
-            {
-              gs->n += weight;
-              gs->sum += weight * val->f;
-              gs->ssq += weight * pow2 (val->f);
-            }
-        }
-    }
-
-  for (i = 0; i < proc->n_vars; i++)
-    {
-      const struct variable *var = proc->vars[i];
-      struct hsh_table *grp_hash = group_proc_get (var)->group_hash;
-      struct hsh_iterator g;
-      struct group_statistics *gs;
-      int count = 0;
-
-      for (gs = hsh_first (grp_hash, &g); gs != NULL;
-          gs = hsh_next (grp_hash, &g))
-       {
-         gs->mean = gs->sum / gs->n;
-         gs->s_std_dev = sqrt (((gs->ssq / gs->n) - pow2 (gs->mean)));
-         gs->std_dev = sqrt (gs->n / (gs->n- 1)
-                              * ((gs->ssq / gs->n) - pow2 (gs->mean)));
-         gs->se_mean = gs->std_dev / sqrt (gs->n);
-         count++;
-       }
-      assert (count == 2);
-    }
-
-  casereader_destroy (reader);
-
-  return 0;
-}
-
-
-static bool
-is_criteria_value (const struct ccase *c, void *aux)
-{
-  const struct t_test_proc *proc = aux;
-  const union value *val = case_data (c, proc->indep_var);
-  int width = var_get_width (proc->indep_var);
-
-  if ( value_equal (val, &proc->g_value[0], width))
-    return true;
-
-  if ( value_equal (val, &proc->g_value[1], width))
-    return true;
-
-  return false;
-}
-
-static void
-calculate (struct t_test_proc *proc,
-           struct casereader *input, const struct dataset *ds)
-{
-  const struct dictionary *dict = dataset_dict (ds);
-  struct ssbox stat_summary_box;
-  struct trbox test_results_box;
-  struct taint *taint;
-  struct ccase *c;
-  int i;
-  c = casereader_peek (input, 0);
-  if (c == NULL)
-    {
-      casereader_destroy (input);
-      return;
-    }
-  output_split_file_values (ds, c);
-  case_unref (c);
-
-  if (proc->listwise_missing)
-    input = casereader_create_filter_missing (input,
-                                              proc->vars,
-                                              proc->n_vars,
-                                              proc->exclude, NULL, NULL);
-  input = casereader_create_filter_weight (input, dict, NULL, NULL);
-  taint = taint_clone (casereader_get_taint (input));
-
-  common_calc (dict, proc, casereader_clone (input));
-  switch (proc->mode)
-    {
-    case T_1_SAMPLE:
-      one_sample_calc (dict, proc, input);
-      break;
-    case T_PAIRED:
-      paired_calc (dict, proc, input);
-      break;
-    case T_IND_SAMPLES:
-      group_calc (dict, proc, casereader_clone (input));
-
-      for (i = 0; i < proc->n_vars; ++i)
-       {
-         struct group_proc *grp_data = group_proc_get (proc->vars[i]);
-
-         if ( proc->criterion == CMP_EQ )
-           {
-             input = casereader_create_filter_func (input, is_criteria_value, NULL,
-                                                    proc, 
-                                                    NULL);
-           }
-
-         grp_data->levene = levene ( input, proc->indep_var, proc->vars[i], dict_get_weight (dict), proc->exclude);
-       }
-      break;
-    default:
-      NOT_REACHED ();
-    }
-
-  if (!taint_has_tainted_successor (taint))
-    {
-      ssbox_create (&stat_summary_box, proc);
-      ssbox_populate (&stat_summary_box, proc);
-      ssbox_finalize (&stat_summary_box);
-
-      if (proc->mode == T_PAIRED)
-        pscbox (proc);
-
-      trbox_create (&test_results_box, proc);
-      trbox_populate (&test_results_box, proc);
-      trbox_finalize (&test_results_box);
-    }
-
-  taint_destroy (taint);
-}
-
-/* return 0 if G belongs to group 0,
-          1 if it belongs to group 1,
-          2 if it belongs to neither group */
-static int
-which_group (const struct group_statistics *g,
-             const struct t_test_proc *proc)
-{
-  int width = var_get_width (proc->indep_var);
-
-  if (0 == value_compare_3way (&g->id, &proc->g_value[0], width))
-    return 0;
-
-  if (0 == value_compare_3way (&g->id, &proc->g_value[1], width))
-    return 1;
-
-  return 2;
-}
-
-/* Return -1 if the id of a is less than b; +1 if greater than and
-   0 if equal */
-static int
-compare_group_binary (const struct group_statistics *a,
-                      const struct group_statistics *b,
-                      const struct t_test_proc *proc)
-{
-  int flag_a;
-  int flag_b;
-
-  if (proc->criterion == CMP_LE)
-    {
-      flag_a = (a->id.f < proc->critical_value);
-      flag_b = (b->id.f < proc->critical_value);
-    }
-  else
-    {
-      flag_a = which_group (a, proc);
-      flag_b = which_group (b, proc);
-    }
-
-  if (flag_a < flag_b)
-    return - 1;
-
-  return (flag_a > flag_b);
-}
-
-/* This is a degenerate case of a hash, since it can only return three possible
-   values.  It's really a comparison, being used as a hash function */
-
-static unsigned
-hash_group_binary (const struct group_statistics *g,
-                   const struct t_test_proc *proc)
-{
-  return (proc->criterion == CMP_LE
-          ? g->id.f < proc->critical_value
-          : which_group (g, proc));
-}
-
-/*
-  Local Variables:
-  mode: c
-  End:
-*/
index e4948406d034bde5762a55288766d5e0fb4d7eaf..805887410b13a31b9e185ab9c7a51c6e5080a080 100644 (file)
@@ -30,8 +30,8 @@ src_libpspp_libpspp_la_SOURCES = \
        src/libpspp/freaderror.h \
        src/libpspp/hash-functions.c \
        src/libpspp/hash-functions.h \
-       src/libpspp/hash.c \
-       src/libpspp/hash.h \
+       src/libpspp/inflate.c \
+       src/libpspp/inflate.h \
        src/libpspp/heap.c \
        src/libpspp/heap.h \
        src/libpspp/hmap.c \
@@ -89,6 +89,9 @@ src_libpspp_libpspp_la_SOURCES = \
        src/libpspp/u8-istream.c \
        src/libpspp/u8-istream.h \
        src/libpspp/version.h \
+       src/libpspp/zip-private.h \
+       src/libpspp/zip-reader.c \
+       src/libpspp/zip-reader.h \
        src/libpspp/zip-writer.c \
        src/libpspp/zip-writer.h
 
index 00e42d6603cc68963f498c6d5ce0ab780c1b19f6..802698da23ae2fcca48c158d464b4efd8b34eedb 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2009, 2010, 2011 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
    not yet carefully examined the situation, or if you are not sure.
    Use CHAR_CAST if you are convinced that this is actually a correct cast. */
 #define CHAR_CAST(TYPE, POINTER)                                \
-        ((void) verify_true (sizeof (*(POINTER)) == 1),         \
-         (void) (sizeof (*(POINTER) + 1)),                      \
-         (void) verify_true (sizeof (*(TYPE) NULL) == 1),       \
-         (void) (sizeof (*(TYPE) NULL + 1)),                    \
-         (TYPE) (POINTER))
+  ((void) verify_expr (sizeof (*(POINTER)) == 1, 1),            \
+   (void) (sizeof (*(POINTER) + 1)),                            \
+   (void) verify_expr (sizeof (*(TYPE) NULL) == 1, 1),          \
+   (void) (sizeof (*(TYPE) NULL + 1)),                          \
+   (TYPE) (POINTER))
 #define CHAR_CAST_BUG(TYPE, POINTER) CHAR_CAST(TYPE, POINTER)
 
 /* Given POINTER, a pointer to the given MEMBER within structure
index 68bbe954f38768d80d48a9c1f90ae71873daf086..57ff8e4a7d6225e3b56c9b71c0760e6e9570f635 100644 (file)
@@ -69,7 +69,7 @@ ext_array_destroy (struct ext_array *ea)
     {
       ok = !ext_array_error (ea);
       if (ea->file != NULL)
-        fclose (ea->file);
+        close_temp_file (ea->file);
       free (ea);
     }
   return ok;
diff --git a/src/libpspp/hash.c b/src/libpspp/hash.c
deleted file mode 100644 (file)
index f2d99e3..0000000
+++ /dev/null
@@ -1,581 +0,0 @@
-/* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2008 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 <assert.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <stdlib.h>
-
-#include "array.h"
-#include "compiler.h"
-#include "hash.h"
-#include "misc.h"
-#include "pool.h"
-#include "str.h"
-
-#include "xalloc.h"
-
-#include "gettext.h"
-#define _(msgid) gettext (msgid)
-
-/* Note for constructing hash functions:
-
-   You can store the hash values in the records, then compare hash
-   values (in the compare function) before bothering to compare keys.
-   Hash values can simply be returned from the records instead of
-   recalculating when rehashing. */
-
-/* Debugging note:
-
-   Since hash_probe and hash_find take void * pointers, it's easy to
-   pass a void ** to your data by accidentally inserting an `&'
-   reference operator where one shouldn't go.  It took me an hour to
-   hunt down a bug like that once. */
-\f
-/* Prime numbers and hash functions. */
-
-/* Returns smallest power of 2 greater than X. */
-static size_t
-next_power_of_2 (size_t x)
-{
-  assert (x != 0);
-
-  for (;;)
-    {
-      /* Turn off rightmost 1-bit in x. */
-      size_t y = x & (x - 1);
-
-      /* If y is 0 then x only had a single 1-bit. */
-      if (y == 0)
-        return 2 * x;
-
-      /* Otherwise turn off the next. */
-      x = y;
-    }
-}
-
-\f
-/* Hash tables. */
-
-/* Hash table. */
-struct hsh_table
-  {
-    size_t used;                /* Number of filled entries. */
-    size_t size;                /* Number of entries (a power of 2). */
-    void **entries;            /* Hash table proper. */
-
-    const void *aux;            /* Auxiliary data for comparison functions. */
-    hsh_compare_func *compare;
-    hsh_hash_func *hash;
-    hsh_free_func *free;
-
-#ifndef NDEBUG
-    /* Set to false if hsh_data() or hsh_sort() has been called,
-       so that most hsh_*() functions may no longer be called. */
-    bool hash_ordered;
-#endif
-
-    struct pool *pool;         /* The pool used for this hash table */
-  };
-
-struct hsh_table *
-hsh_create (int size, hsh_compare_func *compare, hsh_hash_func *hash,
-            hsh_free_func *free, const void *aux)
-{
-  return hsh_create_pool (NULL, size, compare, hash, free, aux);
-}
-
-
-
-/* Creates a hash table with at least M entries.  COMPARE is a
-   function that compares two entries and returns 0 if they are
-   identical, nonzero otherwise; HASH returns a nonnegative hash value
-   for an entry; FREE destroys an entry. */
-struct hsh_table *
-hsh_create_pool (struct pool *pool, int size,
-                hsh_compare_func *compare, hsh_hash_func *hash,
-                hsh_free_func *free, const void *aux)
-{
-  struct hsh_table *h;
-  int i;
-
-  assert (compare != NULL);
-  assert (hash != NULL);
-
-  h = pool_malloc (pool, sizeof *h);
-  h->pool = pool;
-  h->used = 0;
-  if (size < 4)
-    size = 4;
-  h->size = next_power_of_2 (size);
-  h->entries = pool_nmalloc (pool, h->size, sizeof *h->entries);
-  for (i = 0; i < h->size; i++)
-    h->entries[i] = NULL;
-  h->aux = aux;
-  h->compare = compare;
-  h->hash = hash;
-  h->free = free;
-#ifndef NDEBUG
-  h->hash_ordered = true;
-#endif
-  return h;
-}
-
-/* Destroys the contents of table H. */
-void
-hsh_clear (struct hsh_table *h)
-{
-  int i;
-
-  assert (h != NULL);
-  if (h->free)
-    for (i = 0; i < h->size; i++)
-      if (h->entries[i] != NULL)
-        h->free (h->entries[i], h->aux);
-
-  for (i = 0; i < h->size; i++)
-    h->entries[i] = NULL;
-
-  h->used = 0;
-
-#ifndef NDEBUG
-  h->hash_ordered = true;
-#endif
-}
-
-/* Destroys table H and all its contents. */
-void
-hsh_destroy (struct hsh_table *h)
-{
-  int i;
-
-  if (h != NULL)
-    {
-      if (h->free)
-        for (i = 0; i < h->size; i++)
-          if (h->entries[i] != NULL)
-            h->free (h->entries[i], h->aux);
-      pool_free (h->pool, h->entries);
-      pool_free (h->pool, h);
-    }
-}
-
-/* Locates an entry matching TARGET.  Returns the index for the
-   entry, if found, or the index of an empty entry that indicates
-   where TARGET should go, otherwise. */
-static inline unsigned
-locate_matching_entry (struct hsh_table *h, const void *target)
-{
-  unsigned i = h->hash (target, h->aux);
-
-  assert (h->hash_ordered);
-  for (;;)
-    {
-      void *entry;
-      i &= h->size - 1;
-      entry = h->entries[i];
-      if (entry == NULL || !h->compare (entry, target, h->aux))
-       return i;
-      i--;
-    }
-}
-
-/* Returns the index of an empty entry that indicates
-   where TARGET should go, assuming that TARGET is not equal to
-   any item already in the hash table. */
-static inline unsigned
-locate_empty_entry (struct hsh_table *h, const void *target)
-{
-  unsigned i = h->hash (target, h->aux);
-
-  assert (h->hash_ordered);
-  for (;;)
-    {
-      i &= h->size - 1;
-      if (h->entries[i] == NULL)
-       return i;
-      i--;
-    }
-}
-
-/* Changes the capacity of H to NEW_SIZE, which must be a
-   positive power of 2 at least as large as the number of
-   elements in H. */
-static void
-rehash (struct hsh_table *h, size_t new_size)
-{
-  void **begin, **end, **table_p;
-  int i;
-
-  assert (h != NULL);
-  assert (new_size >= h->used);
-
-  /* Verify that NEW_SIZE is a positive power of 2. */
-  assert (new_size > 0 && (new_size & (new_size - 1)) == 0);
-
-  begin = h->entries;
-  end = begin + h->size;
-
-  h->size = new_size;
-  h->entries = pool_nmalloc (h->pool, h->size, sizeof *h->entries);
-  for (i = 0; i < h->size; i++)
-    h->entries[i] = NULL;
-  for (table_p = begin; table_p < end; table_p++)
-    {
-      void *entry = *table_p;
-      if (entry != NULL)
-        h->entries[locate_empty_entry (h, entry)] = entry;
-    }
-  pool_free (h->pool, begin);
-
-#ifndef NDEBUG
-  h->hash_ordered = true;
-#endif
-}
-
-/* A "algo_predicate_func" that returns true if DATA points
-   to a non-null void. */
-static bool
-not_null (const void *data_, const void *aux UNUSED)
-{
-  void *const *data = data_;
-
-  return *data != NULL;
-}
-
-/* Compacts hash table H and returns a pointer to its data.  The
-   returned data consists of hsh_count(H) non-null pointers, in
-   no particular order, followed by a null pointer.
-
-   After calling this function, only hsh_destroy() and
-   hsh_count() should be applied to H.  hsh_first() and
-   hsh_next() could also be used, but you're better off just
-   iterating through the returned array.
-
-   This function is intended for use in situations where data
-   processing occurs in two phases.  In the first phase, data is
-   added, removed, and searched for within a hash table.  In the
-   second phase, the contents of the hash table are output and
-   the hash property itself is no longer of interest.
-
-   Use hsh_sort() instead, if the second phase wants data in
-   sorted order.  Use hsh_data_copy() or hsh_sort_copy() instead,
-   if the second phase still needs to search the hash table. */
-void *const *
-hsh_data (struct hsh_table *h)
-{
-  size_t n;
-
-  assert (h != NULL);
-  n = partition (h->entries, h->size, sizeof *h->entries, not_null, NULL);
-  assert (n == h->used);
-#ifndef NDEBUG
-  h->hash_ordered = false;
-#endif
-  return h->entries;
-}
-
-/* Dereferences void ** pointers and passes them to the hash
-   comparison function. */
-static int
-comparison_helper (const void *a_, const void *b_, const void *h_)
-{
-  void *const *a = a_;
-  void *const *b = b_;
-  const struct hsh_table *h = h_;
-
-  assert(a);
-  assert(b);
-
-  return h->compare (*a, *b, h->aux);
-}
-
-/* Sorts hash table H based on hash comparison function.  The
-   returned data consists of hsh_count(H) non-null pointers,
-   sorted in order of the hash comparison function, followed by a
-   null pointer.
-
-   After calling this function, only hsh_destroy() and
-   hsh_count() should be applied to H.  hsh_first() and
-   hsh_next() could also be used, but you're better off just
-   iterating through the returned array.
-
-   This function is intended for use in situations where data
-   processing occurs in two phases.  In the first phase, data is
-   added, removed, and searched for within a hash table.  In the
-   second phase, the contents of the hash table are output and
-   the hash property itself is no longer of interest.
-
-   Use hsh_data() instead, if the second phase doesn't need the
-   data in any particular order.  Use hsh_data_copy() or
-   hsh_sort_copy() instead, if the second phase still needs to
-   search the hash table. */
-void *const *
-hsh_sort (struct hsh_table *h)
-{
-  assert (h != NULL);
-
-  hsh_data (h);
-  sort (h->entries, h->used, sizeof *h->entries, comparison_helper, h);
-  return h->entries;
-}
-
-/* Makes and returns a copy of the pointers to the data in H.
-   The returned data consists of hsh_count(H) non-null pointers,
-   in no particular order, followed by a null pointer.  The hash
-   table is not modified.  The caller is responsible for freeing
-   the allocated data.
-
-   If you don't need to search or modify the hash table, then
-   hsh_data() is a more efficient choice. */
-void **
-hsh_data_copy (struct hsh_table *h)
-{
-  void **copy;
-
-  assert (h != NULL);
-  copy = pool_nmalloc (h->pool, (h->used + 1), sizeof *copy);
-  copy_if (h->entries, h->size, sizeof *h->entries, copy, not_null, NULL);
-  copy[h->used] = NULL;
-  return copy;
-}
-
-/* Makes and returns a copy of the pointers to the data in H.
-   The returned data consists of hsh_count(H) non-null pointers,
-   sorted in order of the hash comparison function, followed by a
-   null pointer.  The hash table is not modified.  The caller is
-   responsible for freeing the allocated data.
-
-   If you don't need to search or modify the hash table, then
-   hsh_sort() is a more efficient choice. */
-void **
-hsh_sort_copy (struct hsh_table *h)
-{
-  void **copy;
-
-  assert (h != NULL);
-  copy = hsh_data_copy (h);
-  sort (copy, h->used, sizeof *copy, comparison_helper, h);
-  return copy;
-}
-\f
-/* Hash entries. */
-
-/* Searches hash table H for TARGET.  If found, returns a pointer
-   to a pointer to that entry; otherwise returns a pointer to a
-   NULL entry which *must* be used to insert a new entry having
-   the same key data.  */
-void **
-hsh_probe (struct hsh_table *h, const void *target)
-{
-  unsigned i;
-
-  assert (h != NULL);
-  assert (target != NULL);
-  assert (h->hash_ordered);
-
-  if (h->used > h->size / 2)
-    rehash (h, h->size * 2);
-  i = locate_matching_entry (h, target);
-  if (h->entries[i] == NULL)
-    h->used++;
-  return &h->entries[i];
-}
-
-/* Searches hash table H for TARGET.  If not found, inserts
-   TARGET and returns a null pointer.  If found, returns the
-   match, without replacing it in the table. */
-void *
-hsh_insert (struct hsh_table *h, void *target)
-{
-  void **entry;
-
-  assert (h != NULL);
-  assert (target != NULL);
-
-  entry = hsh_probe (h, target);
-  if (*entry == NULL)
-    {
-      *entry = target;
-      return NULL;
-    }
-  else
-    return *entry;
-}
-
-/* Searches hash table H for TARGET.  If not found, inserts
-   TARGET and returns a null pointer.  If found, returns the
-   match, after replacing it in the table by TARGET. */
-void *
-hsh_replace (struct hsh_table *h, void *target)
-{
-  void **entry = hsh_probe (h, target);
-  void *old = *entry;
-  *entry = target;
-  return old;
-}
-
-/* Returns the entry in hash table H that matches TARGET, or NULL
-   if there is none. */
-void *
-hsh_find (struct hsh_table *h, const void *target)
-{
-  return h->entries[locate_matching_entry (h, target)];
-}
-
-/* Deletes the entry in hash table H that matches TARGET.
-   Returns true if an entry was deleted.
-
-   Uses Knuth's Algorithm 6.4R (Deletion with linear probing).
-   Because our load factor is at most 1/2, the average number of
-   moves that this algorithm makes should be at most 2 - ln 2 ~=
-   1.65. */
-bool
-hsh_delete (struct hsh_table *h, const void *target)
-{
-  unsigned i = locate_matching_entry (h, target);
-  if (h->entries[i] != NULL)
-    {
-      h->used--;
-      if (h->free != NULL)
-        h->free (h->entries[i], h->aux);
-
-      for (;;)
-        {
-          unsigned r;
-          ptrdiff_t j;
-
-          h->entries[i] = NULL;
-          j = i;
-          do
-            {
-              i = (i - 1) & (h->size - 1);
-              if (h->entries[i] == NULL)
-                return true;
-
-              r = h->hash (h->entries[i], h->aux) & (h->size - 1);
-            }
-          while ((i <= r && r < j) || (r < j && j < i) || (j < i && i <= r));
-          h->entries[j] = h->entries[i];
-        }
-    }
-  else
-    return false;
-}
-\f
-/* Iteration. */
-
-/* Finds and returns an entry in TABLE, and initializes ITER for
-   use with hsh_next().  If TABLE is empty, returns a null
-   pointer. */
-void *
-hsh_first (struct hsh_table *h, struct hsh_iterator *iter)
-{
-  assert (h != NULL);
-  assert (iter != NULL);
-
-  iter->next = 0;
-  return hsh_next (h, iter);
-}
-
-/* Iterates through TABLE with iterator ITER.  Returns the next
-   entry in TABLE, or a null pointer after the last entry.
-
-   Entries are returned in an undefined order.  Modifying TABLE
-   during iteration may cause some entries to be returned
-   multiple times or not at all. */
-void *
-hsh_next (struct hsh_table *h, struct hsh_iterator *iter)
-{
-  size_t i;
-
-  assert (h != NULL);
-  assert (iter != NULL);
-  assert (iter->next <= h->size);
-
-  for (i = iter->next; i < h->size; i++)
-    if (h->entries[i])
-      {
-       iter->next = i + 1;
-       return h->entries[i];
-      }
-
-  iter->next = h->size;
-  return NULL;
-}
-\f
-/* Returns the number of items in H. */
-size_t
-hsh_count (struct hsh_table *h)
-{
-  assert (h != NULL);
-
-  return h->used;
-}
-\f
-/* Debug helpers. */
-
-#if DEBUGGING
-#undef NDEBUG
-#include "message.h"
-#include <stdio.h>
-
-/* Displays contents of hash table H on stdout. */
-void
-hsh_dump (struct hsh_table *h)
-{
-  void **entry = h->entries;
-  int i;
-
-  printf ("hash table:");
-  for (i = 0; i < h->size; i++)
-    printf (" %p", *entry++);
-  printf ("\n");
-}
-
-/* This wrapper around hsh_probe() assures that it returns a pointer
-   to a NULL pointer.  This function is used when it is known that the
-   entry to be inserted does not already exist in the table. */
-void
-hsh_force_insert (struct hsh_table *h, void *p)
-{
-  void **pp = hsh_probe (h, p);
-  assert (*pp == NULL);
-  *pp = p;
-}
-
-/* This wrapper around hsh_find() assures that it returns non-NULL.
-   This function is for use when it is known that the entry being
-   searched for must exist in the table. */
-void *
-hsh_force_find (struct hsh_table *h, const void *target)
-{
-  void *found = hsh_find (h, target);
-  assert (found != NULL);
-  return found;
-}
-
-/* This wrapper for hsh_delete() verifies that an item really was
-   deleted. */
-void
-hsh_force_delete (struct hsh_table *h, const void *target)
-{
-  int found = hsh_delete (h, target);
-  assert (found != 0);
-}
-#endif
diff --git a/src/libpspp/hash.h b/src/libpspp/hash.h
deleted file mode 100644 (file)
index 3281c0e..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-/* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2009, 2011 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/>. */
-
-#if !hash_h
-#define hash_h 1
-
-#include <stddef.h>
-#include <stdbool.h>
-#include "libpspp/hash-functions.h"
-
-typedef int hsh_compare_func (const void *, const void *, const void *aux);
-typedef unsigned hsh_hash_func (const void *, const void *aux);
-typedef void hsh_free_func (void *, const void *aux);
-
-/* Hash table iterator (opaque). */
-struct hsh_iterator
-  {
-    size_t next;               /* Index of next entry. */
-  };
-
-/* Hash tables. */
-struct hsh_table *hsh_create (int m, hsh_compare_func *,
-                              hsh_hash_func *, hsh_free_func *,
-                             const void *aux);
-
-struct pool;
-struct hsh_table *hsh_create_pool (struct pool *pool, int m,
-                                  hsh_compare_func *,
-                                  hsh_hash_func *, hsh_free_func *,
-                                  const void *aux);
-
-void hsh_clear (struct hsh_table *);
-void hsh_destroy (struct hsh_table *);
-void *const *hsh_sort (struct hsh_table *);
-void *const *hsh_data (struct hsh_table *);
-void **hsh_sort_copy (struct hsh_table *);
-void **hsh_data_copy (struct hsh_table *);
-
-/* Search and insertion. */
-void **hsh_probe (struct hsh_table *, const void *);
-void *hsh_insert (struct hsh_table *, void *);
-void *hsh_replace (struct hsh_table *, void *);
-void *hsh_find (struct hsh_table *, const void *);
-bool hsh_delete (struct hsh_table *, const void *);
-
-/* Iteration. */
-void *hsh_first (struct hsh_table *, struct hsh_iterator *);
-void *hsh_next (struct hsh_table *, struct hsh_iterator *);
-
-/* Search and insertion with assertion. */
-#if DEBUGGING
-void hsh_force_insert (struct hsh_table *, void *);
-void *hsh_force_find (struct hsh_table *, const void *);
-void hsh_force_delete (struct hsh_table *, const void *);
-#else
-#define hsh_force_insert(A, B)  ((void) (*hsh_probe (A, B) = B))
-#define hsh_force_find(A, B)    (hsh_find (A, B))
-#define hsh_force_delete(A, B)  ((void) hsh_delete (A, B))
-#endif
-
-/* Number of entries in hash table H. */
-size_t hsh_count (struct hsh_table *);
-
-/* Debugging. */
-#if DEBUGGING
-void hsh_dump (struct hsh_table *);
-#endif
-
-
-/* Const Wrappers for the above */
-
-static inline struct const_hsh_table *
-const_hsh_create (int m,
-                 hsh_compare_func *hcf,
-                 hsh_hash_func *hhf, hsh_free_func *hff,
-                 const void *aux)
-{
-  return (struct const_hsh_table *) hsh_create (m, hcf, hhf, hff, aux);
-}
-
-
-
-static inline struct const_hsh_table *
-const_hsh_create_pool (struct pool *pool, int m,
-                      hsh_compare_func *cf,
-                      hsh_hash_func *hf, hsh_free_func *ff,
-                      const void *aux)
-{
-  return (struct const_hsh_table *) hsh_create_pool (pool, m, cf, hf, ff, aux);
-}
-
-
-static inline void
-const_hsh_clear (struct const_hsh_table *h)
-{
-  hsh_clear ( (struct hsh_table *) h);
-}
-
-static inline void
-const_hsh_destroy (struct const_hsh_table *h)
-{
-  hsh_destroy ( (struct hsh_table *) h);
-}
-
-static inline void *const *
-const_hsh_sort (struct const_hsh_table *h)
-{
-  return hsh_sort ( (struct hsh_table *) h);
-}
-
-static inline void *const *
-const_hsh_data (struct const_hsh_table *h)
-{
-  return hsh_data ( (struct hsh_table *) h);
-}
-
-static inline void **
-const_hsh_sort_copy (struct const_hsh_table *h)
-{
-  return hsh_sort_copy ( (struct hsh_table *) h);
-}
-
-static inline void **
-const_hsh_data_copy (struct const_hsh_table *h)
-{
-  return hsh_data_copy ( (struct hsh_table *) h);
-}
-
-
-static inline size_t
-const_hsh_count (struct const_hsh_table *h)
-{
-  return hsh_count ( (struct hsh_table *) h);
-}
-
-static inline void *
-const_hsh_insert (struct const_hsh_table *h, const void *item)
-{
-  return hsh_insert ( (struct hsh_table *) h, (void *) item);
-}
-
-static inline void *
-const_hsh_replace (struct const_hsh_table *h, const void *item)
-{
-  return hsh_replace ( (struct hsh_table *) h, (void *) item);
-}
-
-static inline void *
-const_hsh_find (struct const_hsh_table *h, const void *item)
-{
-  return hsh_find ( (struct hsh_table *) h, (void *) item);
-}
-
-static inline bool
-const_hsh_delete (struct const_hsh_table *h, const void *item)
-{
-  return hsh_delete ( (struct hsh_table *)h, (void *) item);
-}
-
-
-static inline void *
-const_hsh_first (struct const_hsh_table *h, struct hsh_iterator *i)
-{
-  return hsh_first ( (struct hsh_table *) h, i);
-}
-
-static inline void *
-const_hsh_next (struct const_hsh_table *h, struct hsh_iterator *i)
-{
-  return hsh_next ( (struct hsh_table *) h, i);
-}
-
-
-#endif /* hash_h */
diff --git a/src/libpspp/inflate.c b/src/libpspp/inflate.c
new file mode 100644 (file)
index 0000000..c4ad1cf
--- /dev/null
@@ -0,0 +1,149 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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 "inflate.h"
+
+#if HAVE_ZLIB_H
+
+#include <xalloc.h>
+#include <zlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "zip-reader.h"
+
+#include "str.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) (msgid)
+
+#define UCOMPSIZE 4096
+
+struct inflator
+{
+  z_stream zss;
+  int state;
+  unsigned char ucomp[UCOMPSIZE];
+  size_t bytes_uncomp;
+  size_t ucomp_bytes_read;
+
+  /* Two bitfields as defined by RFC1950 */
+  uint16_t cmf_flg ;
+};
+
+void
+inflate_finish (struct zip_member *zm)
+{
+  struct inflator *inf = zm->aux;
+
+  inflateEnd (&inf->zss);
+
+  free (inf);
+}
+
+bool
+inflate_init (struct zip_member *zm)
+{
+  int r;
+  struct inflator *inf = xzalloc (sizeof *inf);
+  
+  uint16_t flg = 0 ; 
+  uint16_t cmf = 0x8; /* Always 8 for inflate */
+
+  const uint16_t cinfo = 7;  /* log_2(Window size) - 8 */
+
+  cmf |= cinfo << 4;     /* Put cinfo into the high nibble */
+
+  /* make these into a 16 bit word */
+  inf->cmf_flg = (cmf << 8 ) | flg;
+
+  /* Set the check bits */
+  inf->cmf_flg += 31 - (inf->cmf_flg % 31);
+  assert (inf->cmf_flg % 31 == 0);
+
+  inf->zss.next_in = Z_NULL;
+  inf->zss.avail_in = 0;
+  inf->zss.zalloc = Z_NULL;
+  inf->zss.zfree  = Z_NULL;
+  inf->zss.opaque = Z_NULL;
+  r = inflateInit (&inf->zss);
+
+  if ( Z_OK != r)
+    {
+      ds_put_format (zm->errs, _("Cannot initialize inflator: %s"), zError (r));
+      return false;
+    }
+
+  zm->aux = inf;
+
+  return true;
+}
+
+
+int
+inflate_read (struct zip_member *zm, void *buf, size_t n)
+{
+  int r;
+  struct inflator *inf = zm->aux;
+
+  if (inf->zss.avail_in == 0)
+    {
+      int bytes_read;
+      int bytes_to_read;
+      int pad = 0;
+
+      if ( inf->state == 0)
+       {
+         inf->ucomp[1] = inf->cmf_flg ;
+         inf->ucomp[0] = inf->cmf_flg >> 8 ;
+
+         pad = 2;
+         inf->state++;
+       }
+
+      bytes_to_read = zm->comp_size - inf->ucomp_bytes_read;
+      
+      if (bytes_to_read == 0)
+       return 0;
+
+      if (bytes_to_read > UCOMPSIZE)
+       bytes_to_read = UCOMPSIZE;
+
+      bytes_read = fread (inf->ucomp + pad, 1, bytes_to_read - pad, zm->fp);
+
+      inf->ucomp_bytes_read += bytes_read;
+
+      inf->zss.avail_in = bytes_read + pad;
+      inf->zss.next_in = inf->ucomp;
+    }
+  inf->zss.avail_out = n;
+  inf->zss.next_out = buf;
+
+  r = inflate (&inf->zss, Z_NO_FLUSH);
+  if ( Z_OK == r)
+    {
+      return n - inf->zss.avail_out;
+    }
+  
+  ds_put_format (zm->errs, _("Error inflating: %s"), zError (r));
+
+  return -1;
+}
+
+#endif
diff --git a/src/libpspp/inflate.h b/src/libpspp/inflate.h
new file mode 100644 (file)
index 0000000..c487687
--- /dev/null
@@ -0,0 +1,32 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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/>. */
+
+#ifndef INFLATE_H
+#define INFLATE_H 1
+
+#include <stddef.h>
+#include <stdbool.h>
+
+struct zip_member ;
+
+bool inflate_init (struct zip_member *zm);
+
+int inflate_read (struct zip_member *zm, void *buf, size_t n);
+
+void inflate_finish (struct zip_member *zm);
+
+
+#endif
index ffd5da7cef162dfdaef2ab20e66513b33b67b5ba..9d3c392659753043667af822b9bbfe7bd3e1b0f0 100644 (file)
@@ -19,6 +19,8 @@
 #include <config.h>
 
 #include "libpspp/temp-file.h"
+#include "libpspp/hmapx.h"
+#include "libpspp/hash-functions.h"
 
 #include <stdlib.h>
 
 
      - It honors the $TMPDIR environment variable.
 
-     - The file will not be automatically deleted upon close.  You have to call
-       close_temp_file() if you want it to be deleted before the process exits.
 */
+
+
+static struct temp_dir *temp_dir;
+struct hmapx map;
+
+static void
+setup (void)
+{
+  hmapx_init (&map);
+  temp_dir = create_temp_dir ("pspp", NULL, true);
+}
+
+static void
+cleanup (void)
+{
+  struct hmapx_node *node;
+  char *fn;
+
+  cleanup_temp_dir (temp_dir);
+
+  HMAPX_FOR_EACH (fn, node, &map)
+    {
+      free (fn);
+    }
+
+  hmapx_destroy (&map);
+}
+
 FILE *
 create_temp_file (void)
 {
   static int idx = 0;
-  static struct temp_dir *temp_dir;
   char *file_name;
   FILE *stream;
 
   if (temp_dir == NULL)
     {
-      temp_dir = create_temp_dir ("pspp", NULL, true);
+      setup ();
       if (temp_dir == NULL)
         return NULL;
+      atexit (cleanup);
     }
 
   file_name = xasprintf ("%s/%d", temp_dir->dir_name, idx++);
+  register_temp_file (temp_dir, file_name);
   stream = fopen_temp (file_name, "wb+");
-  if (stream != NULL)
+  if (stream == NULL)
+    unregister_temp_file (temp_dir, file_name);
+  else
     setvbuf (stream, NULL, _IOFBF, 65536);
-  free (file_name);
+
+  hmapx_insert (&map, file_name, hash_pointer (stream, 0));
 
   return stream;
 }
@@ -68,5 +100,12 @@ void
 close_temp_file (FILE *file)
 {
   if (file != NULL)
-    fclose_temp (file);
+    {
+      struct hmapx_node *node = hmapx_first_with_hash (&map, hash_pointer (file, 0));
+      char *fn = node->data;
+      fclose_temp (file);
+      cleanup_temp_file (temp_dir, fn); 
+      hmapx_delete (&map, node);
+      free (fn);
+    }
 }
diff --git a/src/libpspp/zip-private.h b/src/libpspp/zip-private.h
new file mode 100644 (file)
index 0000000..5c956dd
--- /dev/null
@@ -0,0 +1,26 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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/>. */
+
+#ifndef ZIP_PRIVATE_H
+#define ZIP_PRIVATE_H 1
+
+#define MAGIC_EOCD ( (uint32_t) 0x06054b50) /* End of directory */
+#define MAGIC_SOCD ( (uint32_t) 0x02014b50) /* Start of directory */
+#define MAGIC_LHDR ( (uint32_t) 0x04034b50) /* Local Header */
+#define MAGIC_DDHD ( (uint32_t) 0x08074b50) /* Data Descriptor Header */
+
+#endif
+
diff --git a/src/libpspp/zip-reader.c b/src/libpspp/zip-reader.c
new file mode 100644 (file)
index 0000000..bee7e2f
--- /dev/null
@@ -0,0 +1,559 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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 <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <errno.h>
+#include <xalloc.h>
+#include <libpspp/assertion.h>
+
+#include <crc.h>
+
+#include "inflate.h"
+
+#include "str.h"
+
+#include "zip-reader.h"
+#include "zip-private.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) (msgid)
+
+
+static bool find_eocd (FILE *fp, off_t *off);
+
+static int
+stored_read (struct zip_member *zm, void *buf, size_t n)
+{
+  return fread (buf, 1, n, zm->fp);
+}
+
+static bool
+stored_init (struct zip_member *zm UNUSED)
+{
+  return true;
+}
+
+static void
+stored_finish (struct zip_member *zm UNUSED)
+{
+  /* Nothing required */
+}
+
+
+static struct decompressor decompressors[n_COMPRESSION] = 
+  {
+    {stored_init, stored_read, stored_finish},
+#if HAVE_ZLIB_H
+    {inflate_init, inflate_read, inflate_finish}
+#endif
+  };
+
+static enum compression
+comp_code (struct zip_member *zm, uint16_t c)
+{
+  enum compression which;
+  switch (c)
+    {
+    case 0:
+      which = COMPRESSION_STORED;
+      break;
+#if HAVE_ZLIB_H
+    case 8:
+      which = COMPRESSION_INFLATE;
+      break;
+#endif
+    default:
+      ds_put_format (zm->errs, _("Unsupported compression type (%d)"), c);
+      which = n_COMPRESSION;
+      break;
+    }
+  return which;
+}
+
+
+struct zip_reader
+{
+  char *filename;                  /* The name of the file from which the data is read */
+  FILE *fr;                        /* The stream from which the meta data is read */
+  uint16_t n_members;              /* The number of members in this archive */
+  struct zip_member **members;     /* The members (may be null pointers until the headers have been read */
+  int nm;
+  struct string *errs;
+};
+
+void
+zip_member_finish (struct zip_member *zm)
+{
+  ds_clear (zm->errs);
+  /*  Probably not useful, because we would have to read right to the end of the member
+  if (zm->expected_crc != zm->crc)
+    {
+      ds_put_cstr (zm->errs, _("CRC error reading zip"));
+    }
+  */
+  zip_member_unref (zm);
+}
+
+
+
+/* Destroy the zip reader */
+void
+zip_reader_destroy (struct zip_reader *zr)
+{
+  int i;
+  if (zr == NULL) 
+    return;
+
+  fclose (zr->fr);
+  free (zr->filename);
+
+  for (i = 0; i < zr->n_members; ++i)
+    {
+      zip_member_unref (zr->members[i]);
+    }
+  free (zr->members);
+  free (zr);
+}
+
+
+void
+zm_dump (const struct zip_member *zm)
+{
+  printf ("%d\t%08x\t %s\n", zm->ucomp_size, zm->expected_crc, zm->name);
+}
+
+
+/* Skip N bytes in F */
+static void
+skip_bytes (FILE *f, size_t n)
+{
+  fseeko (f, n, SEEK_CUR);
+}
+
+/* Read N bytes from F, storing the result in X */
+static void
+get_bytes (FILE *f, void *x, size_t n)
+{
+  fread (x, 1, n, f);
+}
+
+/* Read a 32 bit value from F */
+static void
+get_u32 (FILE *f, uint32_t *x)
+{
+  get_bytes (f, x, sizeof *x);
+}
+
+
+/* Read 32 bit integer and compare it with EXPECTED.
+   place an error string in ERR if necessary. */
+static bool
+check_magic (FILE *f, uint32_t expected, struct string *err)
+{
+  uint32_t magic;
+
+  get_u32 (f, &magic);
+
+  if ((expected != magic))
+    {
+      ds_put_format (err,
+                    _("Corrupt file at 0x%llx: Expected %"PRIx32"; got %"PRIx32), 
+                    (long long int) ftello (f) - sizeof (uint32_t), expected, magic);
+
+      return false;
+    }
+  return true;
+}
+
+
+/* Read a 16 bit value from F */
+static void
+get_u16 (FILE *f, uint16_t *x)
+{
+  get_bytes (f, x, sizeof *x);
+}
+
+/* Reads upto BYTES bytes from ZM and puts them in BUF.
+   Returns the number of bytes read, or -1 on error */
+int
+zip_member_read (struct zip_member *zm, void *buf, size_t bytes)
+{
+  int bytes_read = 0;
+
+  ds_clear (zm->errs);
+
+  if ( bytes > zm->bytes_unread)
+    bytes = zm->bytes_unread;
+
+  bytes_read  = decompressors[zm->compression].read (zm, buf, bytes);
+  if ( bytes_read < 0)
+    return bytes_read;
+
+  zm->crc = crc32_update (zm->crc, buf, bytes_read);
+
+  zm->bytes_unread -= bytes_read;
+
+  return bytes_read;
+}
+
+
+/*
+  Read a local file header from ZR and add it to ZR's internal array.
+  Returns a pointer to the member read.  This pointer belongs to ZR.
+  If the caller wishes to control it, she should ref it with 
+  zip_member_ref.
+*/
+static struct zip_member *
+zip_header_read_next (struct zip_reader *zr)
+{
+  struct zip_member *zm = xzalloc (sizeof *zm);
+
+  uint16_t v, nlen, extralen;
+  uint16_t gp, time, date;
+  
+  uint16_t clen, diskstart, iattr;
+  uint32_t eattr;
+  uint16_t comp_type;
+
+  ds_clear (zr->errs);
+
+  if ( ! check_magic (zr->fr, MAGIC_SOCD, zr->errs))
+    return NULL;
+
+  get_u16 (zr->fr, &v);
+
+  get_u16 (zr->fr, &v);
+  get_u16 (zr->fr, &gp);
+  get_u16 (zr->fr, &comp_type);
+
+  zm->compression = comp_code (zm, comp_type);
+
+  get_u16 (zr->fr, &time);
+  get_u16 (zr->fr, &date);
+  get_u32 (zr->fr, &zm->expected_crc);
+  get_u32 (zr->fr, &zm->comp_size);
+  get_u32 (zr->fr, &zm->ucomp_size);
+  get_u16 (zr->fr, &nlen);
+  get_u16 (zr->fr, &extralen);
+  get_u16 (zr->fr, &clen);
+  get_u16 (zr->fr, &diskstart);
+  get_u16 (zr->fr, &iattr);
+  get_u32 (zr->fr, &eattr);
+  get_u32 (zr->fr, &zm->offset);
+
+  zm->name = calloc (nlen + 1, 1);
+  get_bytes (zr->fr, zm->name, nlen);
+
+  skip_bytes (zr->fr, extralen);
+  
+  zr->members[zr->nm++] = zm;
+
+  zm->fp = fopen (zr->filename, "r");
+  zm->ref_cnt = 1;
+  zm->errs = zr->errs;
+
+  return zm;
+}
+
+
+/* Create a reader from the zip called FILENAME */
+struct zip_reader *
+zip_reader_create (const char *filename, struct string *errs)
+{
+  uint16_t disknum, total_members;
+  off_t offset = 0;
+  uint32_t central_dir_start, central_dir_length;
+
+  struct zip_reader *zr = malloc (sizeof *zr);
+  zr->errs = errs;
+  if ( zr->errs)
+    ds_init_empty (zr->errs);
+
+  zr->nm = 0;
+
+  zr->fr = fopen (filename, "r");
+  if (NULL == zr->fr)
+    {
+      ds_put_cstr (zr->errs, strerror (errno));
+      free (zr);
+      return NULL;
+    }
+
+  if ( ! check_magic (zr->fr, MAGIC_LHDR, zr->errs))
+    {
+      fclose (zr->fr);
+      free (zr);
+      return NULL;
+    }
+
+  if ( ! find_eocd (zr->fr, &offset))
+    {
+      ds_put_format (zr->errs, _("Cannot find central directory"));
+      fclose (zr->fr);
+      free (zr);
+      return NULL;
+    }
+
+  if ( 0 != fseeko (zr->fr, offset, SEEK_SET))
+    {
+      const char *mm = strerror (errno);
+      ds_put_format (zr->errs, _("Failed to seek to end of central directory record: %s"), mm);
+      fclose (zr->fr);
+      free (zr);
+      return NULL;
+    }
+
+
+  if ( ! check_magic (zr->fr, MAGIC_EOCD, zr->errs))
+    {
+      fclose (zr->fr);
+      free (zr);
+      return NULL;
+    }
+  
+  get_u16 (zr->fr, &disknum);
+  get_u16 (zr->fr, &disknum);
+
+  get_u16 (zr->fr, &zr->n_members);
+  get_u16 (zr->fr, &total_members);
+
+  get_u32 (zr->fr, &central_dir_length);
+  get_u32 (zr->fr, &central_dir_start);
+
+  if ( 0 != fseeko (zr->fr, central_dir_start, SEEK_SET))
+    {
+      const char *mm = strerror (errno);
+      ds_put_format (zr->errs, _("Failed to seek to central directory: %s"), mm);
+      fclose (zr->fr);
+      free (zr);
+      return NULL;
+    }
+
+  zr->members = calloc (zr->n_members, sizeof (*zr->members));
+
+  zr->filename = strdup (filename);
+
+  return zr;
+}
+
+
+
+/* Return the member called MEMBER from the reader ZR  */
+struct zip_member *
+zip_member_open (struct zip_reader *zr, const char *member)
+{
+  uint16_t v, nlen, extra_len;
+  uint16_t gp, comp_type, time, date;
+  uint32_t ucomp_size, comp_size;
+  
+  uint32_t crc;
+
+  char *name = NULL;
+
+  int i;
+  struct zip_member *zm = NULL;
+
+  if ( zr == NULL)
+    return NULL;
+
+  for (i = 0 ; i < zr->n_members; ++i)
+  {
+    zm = zr->members[i] = zip_header_read_next (zr);
+    if (zm && 0 == strcmp (zm->name, member))
+      {
+       break;
+      }
+    else
+      {
+       zm = NULL;
+      }
+  }
+  
+  if ( zm == NULL)
+    return NULL;
+
+  if ( 0 != fseeko (zm->fp, zm->offset, SEEK_SET))
+    {
+      const char *mm = strerror (errno);
+      ds_put_format (zm->errs, _("Failed to seek to start of member `%s': %s"), zm->name, mm);
+      return NULL;
+    }
+
+  if ( ! check_magic (zm->fp, MAGIC_LHDR, zr->errs))
+    {
+      return NULL;
+    }
+
+  get_u16 (zm->fp, &v);
+  get_u16 (zm->fp, &gp);
+  get_u16 (zm->fp, &comp_type);
+  zm->compression = comp_code (zm, comp_type);
+  get_u16 (zm->fp, &time);
+  get_u16 (zm->fp, &date);
+  get_u32 (zm->fp, &crc);
+  get_u32 (zm->fp, &comp_size);
+
+  get_u32 (zm->fp, &ucomp_size);
+  get_u16 (zm->fp, &nlen);
+  get_u16 (zm->fp, &extra_len);
+
+  name = calloc (nlen + 1, sizeof (char));
+
+  get_bytes (zm->fp, name, nlen);
+
+  skip_bytes (zm->fp, extra_len);
+
+  if (strcmp (name, zm->name) != 0)
+    {
+      ds_put_format (zm->errs,
+                    _("Name mismatch in zip archive. Central directory says `%s'; local file header says `%s'"),
+                    zm->name, name);
+      free (name);
+      free (zm);
+      return NULL;
+    }
+
+  free (name);
+
+  zm->bytes_unread = zm->ucomp_size;
+
+  if ( !  decompressors[zm->compression].init (zm) )
+    return NULL;
+
+  return zm;
+}
+
+void
+zip_member_ref (struct zip_member *zm)
+{
+  zm->ref_cnt++;
+}
+
+
+
+
+void
+zip_member_unref (struct zip_member *zm)
+{
+  if ( zm == NULL)
+    return;
+
+  if (--zm->ref_cnt == 0)
+    {
+      decompressors[zm->compression].finish (zm);
+      if (zm->fp)
+       fclose (zm->fp);
+      free (zm->name);
+      free (zm);
+    }
+}
+
+
+\f
+
+static bool probe_magic (FILE *fp, uint32_t magic, off_t start, off_t stop, off_t *off);
+
+
+/* Search for something that looks like the End Of Central Directory in FP.
+   If found, the offset of the record will be placed in OFF.
+   Returns true if found false otherwise.
+*/
+static bool
+find_eocd (FILE *fp, off_t *off)
+{
+  off_t start, stop;
+  const uint32_t magic = MAGIC_EOCD;
+  bool found = false;
+
+  /* The magic cannot be more than 22 bytes from the end of the file, 
+     because that is the minimum length of the EndOfCentralDirectory
+     record.
+   */
+  if ( 0 > fseeko (fp, -22, SEEK_END))
+    {
+      return false;
+    }
+  start = ftello (fp);
+  stop = start + sizeof (magic);
+  do 
+    {
+      found = probe_magic (fp, magic, start, stop, off);
+      /* FIXME: For extra confidence lookup the directory start record here*/
+      if ( start == 0)
+       break;
+      stop = start + sizeof (magic);
+      start >>= 1;
+    }
+  while (!found );
+
+  return found;
+}
+
+
+/*
+  Search FP for MAGIC starting at START and reaching until STOP.
+  Returns true iff MAGIC is found.  False otherwise.
+  OFF receives the location of the magic.
+*/
+static bool
+probe_magic (FILE *fp, uint32_t magic, off_t start, off_t stop, off_t *off)
+{
+  int i;
+  int state = 0;
+  unsigned char seq[4];
+  unsigned char byte;
+
+  if ( 0 > fseeko (fp, start, SEEK_SET))
+    {
+      return -1;
+    }
+
+  for (i = 0; i < 4 ; ++i)
+    {
+      seq[i] = (magic >> i * 8) & 0xFF;
+    }
+
+  do
+    {
+      fread (&byte, 1, 1, fp);
+
+      if ( byte == seq[state])
+       state++;
+      else
+       state = 0;
+      
+      if ( state == 4)
+       {
+         *off = ftello (fp) - 4;
+         return true;
+       }
+      start++;
+      if ( start >= stop)
+       break;
+    }
+  while (!feof (fp));
+
+  return false;
+}
+
diff --git a/src/libpspp/zip-reader.h b/src/libpspp/zip-reader.h
new file mode 100644 (file)
index 0000000..966bd59
--- /dev/null
@@ -0,0 +1,87 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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/>. */
+
+
+#ifndef ZIP_READER_H
+#define ZIP_READER_H 1
+
+#include <inttypes.h>
+
+struct zip_reader;
+struct string;
+
+enum compression
+  {
+    COMPRESSION_STORED = 0,
+#if HAVE_ZLIB_H
+    COMPRESSION_INFLATE,
+#endif
+    n_COMPRESSION
+  };
+
+struct zip_member
+{
+  FILE *fp;                   /* The stream from which the data is read */
+  uint32_t offset;            /* Starting offset in file. */
+  uint32_t comp_size;         /* Length of member file data, in bytes. */
+  uint32_t ucomp_size;        /* Uncompressed length of member file data, in bytes. */
+  uint32_t expected_crc;      /* CRC-32 of member file data.. */
+  char *name;                 /* Name of member file. */
+  uint32_t crc;
+  enum compression compression;
+
+  size_t bytes_unread;       /* Number of bytes left in the member available for reading */
+  int ref_cnt;
+  struct string *errs;
+  void *aux;
+};
+
+struct decompressor
+{
+  bool (*init) (struct zip_member *);
+  int  (*read) (struct zip_member *, void *, size_t);
+  void (*finish) (struct zip_member *);
+};
+
+
+void zm_dump (const struct zip_member *zm);
+
+/* Create zip reader to read the file called FILENAME.
+   If ERRS is non-null if will be used to contain any error messages
+   which the reader wishes to report.
+ */
+struct zip_reader *zip_reader_create (const char *filename, struct string *errs);
+
+/* Destroy the zip reader */
+void zip_reader_destroy (struct zip_reader *zr);
+
+/* Return the zip member in the reader ZR, called MEMBER */
+struct zip_member *zip_member_open (struct zip_reader *zr, const char *member);
+
+/* Read upto N bytes from ZM, storing them in BUF.
+   Returns the number of bytes read, or -1 on error */
+int zip_member_read (struct zip_member *zm, void *buf, size_t n);
+
+/* Unref (and possibly destroy) the zip member ZM */
+void zip_member_unref (struct zip_member *zm);
+
+/* Ref the zip member */
+void zip_member_ref (struct zip_member *zm);
+
+void zip_member_finish (struct zip_member *zm);
+
+
+#endif
index 7e1a6ccc178f5b3e3956c0d3d1e5b1c8f469248b..e93ec887e8be952e08a3db28cd79c4b139ec8249 100644 (file)
@@ -17,6 +17,7 @@
 #include <config.h>
 
 #include "libpspp/zip-writer.h"
+#include "libpspp/zip-private.h"
 
 #include <errno.h>
 #include <stdlib.h>
@@ -120,7 +121,7 @@ zip_writer_add (struct zip_writer *zw, FILE *file, const char *member_name)
 
   /* Local file header. */
   offset = ftello (zw->file);
-  put_u32 (zw, 0x04034b50);     /* local file header signature */
+  put_u32 (zw, MAGIC_LHDR);     /* local file header signature */
   put_u16 (zw, 10);             /* version needed to extract */
   put_u16 (zw, 1 << 3);         /* general purpose bit flag */
   put_u16 (zw, 0);              /* compression method */
@@ -144,7 +145,7 @@ zip_writer_add (struct zip_writer *zw, FILE *file, const char *member_name)
     }
 
   /* Data descriptor. */
-  put_u32 (zw, 0x08074b50);
+  put_u32 (zw, MAGIC_DDHD);
   put_u32 (zw, crc);
   put_u32 (zw, size);
   put_u32 (zw, size);
@@ -179,7 +180,7 @@ zip_writer_close (struct zip_writer *zw)
       struct zip_member *m = &zw->members[i];
 
       /* Central directory file header. */
-      put_u32 (zw, 0x02014b50);       /* central file header signature */
+      put_u32 (zw, MAGIC_SOCD);       /* central file header signature */
       put_u16 (zw, 63);               /* version made by */
       put_u16 (zw, 10);               /* version needed to extract */
       put_u16 (zw, 1 << 3);           /* general purpose bit flag */
@@ -203,7 +204,7 @@ zip_writer_close (struct zip_writer *zw)
   dir_end = ftello (zw->file);
 
   /* End of central directory record. */
-  put_u32 (zw, 0x06054b50);     /* end of central dir signature */
+  put_u32 (zw, MAGIC_EOCD);     /* end of central dir signature */
   put_u16 (zw, 0);              /* number of this disk */
   put_u16 (zw, 0);              /* number of the disk with the
                                    start of the central directory */
index b443d9f94c63f7a0aacebf0ed6447e58dbfdff29..cdcc2c8cb79355d6434a32a6019f21aa6edc3851 100644 (file)
@@ -4,7 +4,8 @@
 noinst_LTLIBRARIES += src/math/libpspp-math.la
 
 src_math_libpspp_math_la_LIBADD = \
-       lib/linreg/liblinreg.la
+       lib/linreg/liblinreg.la \
+       lib/tukey/libtukey.la
 
 src_math_libpspp_math_la_SOURCES = \
        src/math/chart-geometry.c \
@@ -17,8 +18,6 @@ src_math_libpspp_math_la_SOURCES = \
        src/math/correlation.c \
        src/math/correlation.h \
        src/math/extrema.c src/math/extrema.h \
-       src/math/group.c  src/math/group.h \
-       src/math/group-proc.h \
        src/math/histogram.c src/math/histogram.h \
        src/math/interaction.c src/math/interaction.h \
        src/math/levene.c src/math/levene.h \
index f40ae10b5d7dca7714cf8aea4e88314792bea795..d3aa372867249807618885cf697d66984a8233fc 100644 (file)
@@ -17,6 +17,7 @@
 #include <config.h>
 
 #include "math/categoricals.h"
+#include "math/interaction.h"
 
 #include <stdio.h>
 
 #include "libpspp/hmap.h"
 #include "libpspp/pool.h"
 #include "libpspp/str.h"
+#include "libpspp/hash-functions.h"
 
 #include "gl/xalloc.h"
 
 struct value_node
 {
   struct hmap_node node;      /* Node in hash map. */
-  union value value;          /* The value being labeled. */
-  double cc;                  /* The total of the weights of cases with this value */
+
+  union value val;            /* The value */
+
+};
+
+struct interaction_value
+{
+  struct hmap_node node;        /* Node in hash map. */
+
+  struct ccase *ccase;          /* A case (probably the first in the dataset) which matches this value */
+
+  /* Total of the weights of cases matching this interaction */
+  double cc; 
 
   void *user_data;            /* A pointer to data which the caller can store stuff */
+};
+
+static struct value_node *
+lookup_value (const struct hmap *map, const union value *val, unsigned int hash, int width)
+{
+  struct value_node *vn = NULL;
+  HMAP_FOR_EACH_WITH_HASH (vn, struct value_node, node, hash, map)
+    {
+      if (value_equal (&vn->val, val, width))
+       break;
+    }
+  
+  return vn;
+}
 
-  int subscript;              /* A zero based integer, unique within the variable.
-                                Can be used as an index into an array */
+struct variable_node
+{
+  struct hmap_node node;      /* Node in hash map. */
+  const struct variable *var; /* The variable */
+
+  struct hmap valmap;         /* A map of value nodes */
 };
 
-struct var_params
+static void
+dump_interaction (const struct interaction *iact)
+{
+  struct string str = DS_EMPTY_INITIALIZER;
+  interaction_to_string (iact, &str);
+  printf ("Interaction: %s\n", ds_cstr (&str));
+  ds_destroy (&str);
+}
+
+
+static struct variable_node *
+lookup_variable (const struct hmap *map, const struct variable *var, unsigned int hash)
 {
-  /* A map indexed by a union values */
-  struct hmap map;
+  struct variable_node *vn = NULL;
+  HMAP_FOR_EACH_WITH_HASH (vn, struct variable_node, node, hash, map)
+    {
+      if (vn->var == var)
+       break;
+      
+      fprintf (stderr, "Warning: Hash table collision\n");
+    }
+  
+  return vn;
+}
 
-  const struct variable *var;
 
-  int base_subscript;
+struct interact_params
+{
+  /* A map indexed by a interaction_value */
+  struct hmap ivmap;
+
+  const struct interaction *iact;
 
-  /* The number of distinct values of this variable */
+  int base_subscript_short;
+  int base_subscript_long;
+
+  /* The number of distinct values of this interaction */
   int n_cats;
 
-  /* A map of values indexed by subscript */
-  const struct value_node **reverse_value_map;
+  /* The degrees of freedom for this interaction */
+  int df; 
 
-  /* Total of the weights of this variable */
-  double cc; 
+  /* A map of interaction_values indexed by subscript */
+  struct interaction_value **reverse_interaction_value_map;
+
+  double cc;
 };
 
 
 /* Comparison function to sort the reverse_value_map in ascending order */
 static int
-compare_value_node (const void *vn1_, const void *vn2_, const void *aux)
+compare_interaction_value_3way (const void *vn1_, const void *vn2_, const void *aux)
 {
-  const struct value_node * const *vn1 = vn1_;
-  const struct value_node * const *vn2 = vn2_;
-  const struct var_params *vp = aux;
+  const struct interaction_value *const *vn1p = vn1_;
+  const struct interaction_value *const *vn2p = vn2_;
 
-  return value_compare_3way (&(*vn1)->value, &(*vn2)->value, var_get_width (vp->var));
-}
+  const struct interact_params *iap = aux;
 
+  return interaction_case_cmp_3way (iap->iact, (*vn1p)->ccase, (*vn2p)->ccase);
+}
 
 struct categoricals
 {
   /* The weight variable */
   const struct variable *wv;
 
+  /* An array of interact_params */
+  struct interact_params *iap;
 
-  /* An array of var_params */
-  struct var_params *vp;
+  /* Map whose members are the union of the variables which comprise IAP */
+  struct hmap varmap;
 
-  /* The size of VP. (ie, the number of variables involved.) */
-  size_t n_vp;
+  /* The size of IAP. (ie, the number of interactions involved.) */
+  size_t n_iap;
 
   /* The number of categorical variables which contain entries.
-     In the absence of missing values, this will be equal to N_VP */
+     In the absence of missing values, this will be equal to N_IAP */
   size_t n_vars;
 
-  /* A map to enable the lookup of variables indexed by subscript */
-  int *reverse_variable_map;
+  size_t df_sum;
+
+  /* A map to enable the lookup of variables indexed by subscript.
+     This map considers only the N - 1 of the N variables.
+   */
+  int *reverse_variable_map_short;
+
+  /* Like the above, but uses all N variables */
+  int *reverse_variable_map_long;
 
   size_t n_cats_total;
 
@@ -112,100 +181,118 @@ struct categoricals
 };
 
 
-void
-categoricals_destroy ( struct categoricals *cat)
+static void
+categoricals_dump (const struct categoricals *cat)
 {
   int i;
-  if (cat != NULL)
+
+  printf ("Reverse Variable Map (short):\n");
+  for (i = 0; i < cat->df_sum; ++i)
     {
-      for (i = 0 ; i < cat->n_vp; ++i)
-       hmap_destroy (&cat->vp[i].map);
-      
-      pool_destroy (cat->pool);
-      free (cat);
+      printf (" %d", cat->reverse_variable_map_short[i]);
     }
-}
+  printf ("\n");
 
+  printf ("Reverse Variable Map (long):\n");
+  for (i = 0; i < cat->n_cats_total; ++i)
+    {
+      printf (" %d", cat->reverse_variable_map_long[i]);
+    }
+  printf ("\n");
 
-#if 0
-void
-categoricals_dump (const struct categoricals *cat)
-{
-  int v;
 
-  for (v = 0 ; v < cat->n_vp; ++v)
+  printf ("Number of interactions %d\n", cat->n_iap);
+  for (i = 0 ; i < cat->n_iap; ++i)
     {
-      const struct var_params *vp = &cat->vp[v];
-      const struct hmap *m = &vp->map;
-      struct hmap_node *node ;
-      int x;
-     
-      printf ("\n%s (%d)  CC=%g n_cats=%d:\n", 
-             var_get_name (vp->var), vp->base_subscript, vp->cc, vp->n_cats);
-
-      printf ("Reverse map\n");
-      for (x = 0 ; x < vp->n_cats; ++x)
+      int v;
+      struct string str;
+      const struct interact_params *iap = &cat->iap[i];
+      const struct interaction *iact = iap->iact;
+
+      ds_init_empty (&str);
+      interaction_to_string (iact, &str);
+
+      printf ("\nInteraction: %s (n: %d; df: %d ); ", ds_cstr (&str), iap->n_cats, iap->df);
+      ds_destroy (&str);
+      printf ("Base subscript: %d\n", iap->base_subscript_short);
+
+      printf ("\t(");
+      for (v = 0; v < hmap_count (&iap->ivmap); ++v)
        {
-         struct string s;
-         const struct value_node *vn = vp->reverse_value_map[x];
-         ds_init_empty (&s);
-         var_append_value_name (vp->var, &vn->value, &s);
-         printf ("Value for %d is %s\n", x, ds_cstr(&s));
-         ds_destroy (&s);
+         int vv;
+         const struct interaction_value *iv = iap->reverse_interaction_value_map[v];
+         
+         if (v > 0)  printf ("   ");
+         printf ("{");
+         for (vv = 0; vv < iact->n_vars; ++vv)
+           {
+             const struct variable *var = iact->vars[vv];
+             const union value *val = case_data (iv->ccase, var);
+             
+             printf ("%g", val->f);
+             if (vv < iact->n_vars - 1)
+               printf (", ");
+           }
+         printf ("}");
        }
+      printf (")\n");
+    }
+}
 
-      printf ("\nForward map\n");
-      for (node = hmap_first (m); node; node = hmap_next (m, node))
+
+void
+categoricals_destroy (struct categoricals *cat)
+{
+  struct variable_node *vn = NULL;
+  int i;
+  if (NULL == cat)
+    return;
+  for (i = 0; i < cat->n_iap; ++i)
+    {
+      struct interaction_value *iv = NULL;
+      /* Interate over each interaction value, and unref any cases that we reffed */
+      HMAP_FOR_EACH (iv, struct interaction_value, node, &cat->iap[i].ivmap)
        {
-         struct string s;
-         const struct value_node *vn = HMAP_DATA (node, struct value_node, node);
-         ds_init_empty (&s);
-         var_append_value_name (vp->var, &vn->value, &s);
-         printf ("Value: %s; Index %d; CC %g\n",
-                 ds_cstr (&s),
-                 vn->subscript, vn->cc);
-         ds_destroy (&s);
+         case_unref (iv->ccase);
        }
+      hmap_destroy (&cat->iap[i].ivmap);
     }
 
-  assert (cat->n_vars <= cat->n_vp);
+  /* Interate over each variable and delete its value map */
+  HMAP_FOR_EACH (vn, struct variable_node, node, &cat->varmap)
+    {
+      hmap_destroy (&vn->valmap);
+    }
 
-  printf ("\n");
-  printf ("Number of categorical variables: %d\n", cat->n_vp);
-  printf ("Number of non-empty categorical variables: %d\n", cat->n_vars);
-  printf ("Total number of categories: %d\n", cat->n_cats_total);
+  hmap_destroy (&cat->varmap);
 
-  printf ("\nReverse variable map:\n");
+  pool_destroy (cat->pool);
 
-  for (v = 0 ; v < cat->n_cats_total - cat->n_vars; ++v)
-    printf ("%d ", cat->reverse_variable_map[v]);
-  printf ("\n");
+  free (cat);
 }
-#endif
 
 
 
-static struct value_node *
-lookup_value (const struct hmap *map, const struct variable *var, const union value *val)
+static struct interaction_value *
+lookup_case (const struct hmap *map, const struct interaction *iact, const struct ccase *c)
 {
-  struct value_node *foo;
-  unsigned int width = var_get_width (var);
-  size_t hash = value_hash (val, width, 0);
+  struct interaction_value *iv = NULL;
+  size_t hash = interaction_case_hash (iact, c);
 
-  HMAP_FOR_EACH_WITH_HASH (foo, struct value_node, node, hash, map)
+  HMAP_FOR_EACH_WITH_HASH (iv, struct interaction_value, node, hash, map)
     {
-      if (value_equal (val, &foo->value, width))
+      if (interaction_case_equal (iact, c, iv->ccase))
        break;
 
       fprintf (stderr, "Warning: Hash table collision\n");
     }
 
-  return foo;
+  return iv;
 }
 
 
 struct categoricals *
-categoricals_create (const struct variable *const *v, size_t n_vars,
+categoricals_create (struct interaction *const*inter, size_t n_inter,
                     const struct variable *wv, enum mv_class exclude,
                     user_data_create_func *udf,
                     update_func *update, void *aux1, void *aux2
@@ -214,11 +301,12 @@ categoricals_create (const struct variable *const *v, size_t n_vars,
   size_t i;
   struct categoricals *cat = xmalloc (sizeof *cat);
   
-  cat->n_vp = n_vars;
+  cat->n_iap = n_inter;
   cat->wv = wv;
   cat->n_cats_total = 0;
   cat->n_vars = 0;
-  cat->reverse_variable_map = NULL;
+  cat->reverse_variable_map_short = NULL;
+  cat->reverse_variable_map_long = NULL;
   cat->pool = pool_create ();
   cat->exclude = exclude;
   cat->update = update;
@@ -227,13 +315,29 @@ categoricals_create (const struct variable *const *v, size_t n_vars,
   cat->aux1 = aux1;
   cat->aux2 = aux2;
 
+  cat->iap = pool_calloc (cat->pool, cat->n_iap, sizeof *cat->iap);
 
-  cat->vp = pool_calloc (cat->pool, cat->n_vp, sizeof *cat->vp);
-
-  for (i = 0 ; i < cat->n_vp; ++i)
+  hmap_init (&cat->varmap);
+  for (i = 0 ; i < cat->n_iap; ++i)
     {
-      hmap_init (&cat->vp[i].map);
-      cat->vp[i].var = v[i];
+      int v;
+      hmap_init (&cat->iap[i].ivmap);
+      cat->iap[i].iact = inter[i];
+      cat->iap[i].cc = 0.0;
+      for (v = 0; v < inter[i]->n_vars; ++v)
+       {
+         const struct variable *var = inter[i]->vars[v];
+         unsigned int hash = hash_pointer (var, 0);
+         struct variable_node *vn = lookup_variable (&cat->varmap, var, hash);
+         if (vn == NULL)
+           {
+             vn = pool_malloc (cat->pool, sizeof *vn);
+             vn->var = var;
+             hmap_init (&vn->valmap);
+
+             hmap_insert (&cat->varmap, &vn->node,  hash);
+           }
+       }
     }
 
   return cat;
@@ -244,71 +348,96 @@ categoricals_create (const struct variable *const *v, size_t n_vars,
 void
 categoricals_update (struct categoricals *cat, const struct ccase *c)
 {
-  size_t i;
-  
+  int i;
+  struct variable_node *vn = NULL;
   const double weight = cat->wv ? case_data (c, cat->wv)->f : 1.0;
 
-  assert (NULL == cat->reverse_variable_map);
+  assert (NULL == cat->reverse_variable_map_short);
+  assert (NULL == cat->reverse_variable_map_long);
+
+  /* Interate over each variable, and add the value of that variable
+     to the appropriate map, if it's not already present. */
+  HMAP_FOR_EACH (vn, struct variable_node, node, &cat->varmap)
+    {
+      const int width = var_get_width (vn->var);
+      const union value *val = case_data (c, vn->var);
+      unsigned int hash = value_hash (val, width, 0);
+
+      struct value_node *valn = lookup_value (&vn->valmap, val, hash, width);
+      if (valn == NULL)
+       {
+         valn = pool_malloc (cat->pool, sizeof *valn);
+         value_init (&valn->val, width);
+         value_copy (&valn->val, val, width);
+         hmap_insert (&vn->valmap, &valn->node, hash);
+       }
+    }    
+  
 
-  for (i = 0 ; i < cat->n_vp; ++i)
+  for (i = 0 ; i < cat->n_iap; ++i)
     {
-      const struct variable *var = cat->vp[i].var;
-      unsigned int width = var_get_width (var);
-      const union value *val = case_data (c, var);
-      size_t hash;
-      struct value_node *node ;
+      const struct interaction *iact = cat->iap[i].iact;
 
-      if ( var_is_value_missing (var, val, cat->exclude))
-       continue;
+      //      if ( interaction_case_is_missing (iact, c, cat->exclude))
+      //         continue;
 
-      hash = value_hash (val, width, 0);
-      node = lookup_value (&cat->vp[i].map, var, val);
+      size_t hash = interaction_case_hash (iact, c);
+      struct interaction_value *node = lookup_case (&cat->iap[i].ivmap, iact, c);
 
       if ( NULL == node)
        {
          node = pool_malloc (cat->pool, sizeof *node);
 
-         value_init (&node->value, width);
-         value_copy (&node->value, val, width);
-         node->cc = 0.0;
+         node->ccase = case_ref (c);
+         node->cc = weight;
 
-         hmap_insert (&cat->vp[i].map, &node->node,  hash);
-         cat->n_cats_total++;
-         
-         if ( 0 == cat->vp[i].n_cats)
-           cat->n_vars++;
-
-         node->subscript = cat->vp[i].n_cats++ ;
+         hmap_insert (&cat->iap[i].ivmap, &node->node, hash);
 
          if (cat->user_data_create)
            node->user_data = cat->user_data_create (cat->aux1, cat->aux2);
        }
-
-      node->cc += weight;
-      cat->vp[i].cc += weight;
+      else
+       {
+         node->cc += weight;
+       }
+      cat->iap[i].cc += weight;
 
       if (cat->update)
-       cat->update (node->user_data, cat->exclude, cat->wv, var, c, cat->aux1, cat->aux2);
+       cat->update (node->user_data, cat->exclude, cat->wv, NULL, c, cat->aux1, cat->aux2);
     }
 }
 
-/* Return the number of categories (distinct values) for variable N */
+/* Return the number of categories (distinct values) for interction N */
 size_t
 categoricals_n_count (const struct categoricals *cat, size_t n)
 {
-  return hmap_count (&cat->vp[n].map);
+  return hmap_count (&cat->iap[n].ivmap);
+}
+
+
+size_t
+categoricals_df (const struct categoricals *cat, size_t n)
+{
+  return cat->iap[n].df;
 }
 
 
 /* Return the total number of categories */
 size_t
-categoricals_total (const struct categoricals *cat)
+categoricals_n_total (const struct categoricals *cat)
 {
+  assert (cat->reverse_variable_map_long);
+
   return cat->n_cats_total;
 }
 
+size_t
+categoricals_df_total (const struct categoricals *cat)
+{
+  return cat->df_sum;
+}
 
-/* This function must be called *before* any call to categoricals_get_*_by subscript an
+/* This function must be called *before* any call to categoricals_get_*_by subscript and
  *after* all calls to categoricals_update */
 void
 categoricals_done (const struct categoricals *cat_)
@@ -321,79 +450,136 @@ categoricals_done (const struct categoricals *cat_)
   */
   struct categoricals *cat = CONST_CAST (struct categoricals *, cat_);
   int v;
-  int idx = 0;
-  cat->reverse_variable_map = pool_calloc (cat->pool,
-                                          cat->n_cats_total - cat->n_vars,
-                                          sizeof *cat->reverse_variable_map);
-  
-  for (v = 0 ; v < cat->n_vp; ++v)
+  int i;
+  int idx_short = 0;
+  int idx_long = 0;
+  cat->df_sum = 0;
+  cat->n_cats_total = 0;
+
+  /* Calculate the degrees of freedom, and the number of categories */
+  for (i = 0 ; i < cat->n_iap; ++i)
+    {
+      const struct interaction *iact = cat->iap[i].iact;
+
+      cat->iap[i].df = 1;
+      cat->iap[i].n_cats = 1;
+
+      for (v = 0 ; v < iact->n_vars; ++v)
+       {
+         const struct variable *var = iact->vars[v];
+
+         struct variable_node *vn = lookup_variable (&cat->varmap, var, hash_pointer (var, 0));
+
+         cat->iap[i].df *= hmap_count (&vn->valmap) - 1;
+         cat->iap[i].n_cats *= hmap_count (&vn->valmap);
+       }
+
+      cat->df_sum += cat->iap[i].df;
+      cat->n_cats_total += cat->iap[i].n_cats;
+    }
+
+
+  cat->reverse_variable_map_short = pool_calloc (cat->pool,
+                                                cat->df_sum,
+                                                sizeof *cat->reverse_variable_map_short);
+
+  cat->reverse_variable_map_long = pool_calloc (cat->pool,
+                                               cat->n_cats_total,
+                                               sizeof *cat->reverse_variable_map_long);
+
+  for (i = 0 ; i < cat->n_iap; ++i)
     {
-      int i;
-      struct var_params *vp = &cat->vp[v];
-      int n_cats_total = categoricals_n_count (cat, v);
-      struct hmap_node *node ;
+      struct interaction_value *ivn = NULL;
+      int x = 0;
+      int ii;
+      struct interact_params *iap = &cat->iap[i];
 
-      vp->reverse_value_map = pool_calloc (cat->pool, n_cats_total, sizeof *vp->reverse_value_map);
+      iap->base_subscript_short = idx_short;
+      iap->base_subscript_long = idx_long;
 
-      vp->base_subscript = idx;
+      iap->reverse_interaction_value_map = pool_calloc (cat->pool, iap->n_cats,
+                                                       sizeof *iap->reverse_interaction_value_map);
 
-      for (node = hmap_first (&vp->map); node; node = hmap_next (&vp->map, node))
+      HMAP_FOR_EACH (ivn, struct interaction_value, node, &iap->ivmap)
        {
-         const struct value_node *vn = HMAP_DATA (node, struct value_node, node);
-         vp->reverse_value_map[vn->subscript] = vn;
+         iap->reverse_interaction_value_map[x++] = ivn;
        }
 
+      assert (x <= iap->n_cats);
+
       /* For some purposes (eg CONTRASTS in ONEWAY) the values need to be sorted */
-      sort (vp->reverse_value_map, vp->n_cats, sizeof (const struct value_node *),
-           compare_value_node, vp);
+      sort (iap->reverse_interaction_value_map, x, sizeof (*iap->reverse_interaction_value_map),
+           compare_interaction_value_3way, iap);
+
+      /* Fill the remaining values with null */
+      for (ii = x ; ii < iap->n_cats; ++ii)
+       iap->reverse_interaction_value_map[ii] = NULL;
 
-      /* Populate the reverse variable map.
-       */
-      for (i = 0; i < vp->n_cats - 1; ++i)
-       cat->reverse_variable_map[idx++] = v;
+      /* Populate the reverse variable maps. */
+      for (ii = 0; ii < iap->df; ++ii)
+       cat->reverse_variable_map_short[idx_short++] = i;
+
+      for (ii = 0; ii < iap->n_cats; ++ii)
+       cat->reverse_variable_map_long[idx_long++] = i;
     }
 
-  assert (cat->n_vars <= cat->n_vp);
+  assert (cat->n_vars <= cat->n_iap);
+
+  //  categoricals_dump (cat);
 }
 
 
 static int
-reverse_variable_lookup (const struct categoricals *cat, int subscript)
+reverse_variable_lookup_short (const struct categoricals *cat, int subscript)
+{
+  assert (cat->reverse_variable_map_short);
+  assert (subscript >= 0);
+  assert (subscript < cat->df_sum);
+
+  return cat->reverse_variable_map_short[subscript];
+}
+
+static int
+reverse_variable_lookup_long (const struct categoricals *cat, int subscript)
 {
-  assert (cat->reverse_variable_map);
+  assert (cat->reverse_variable_map_long);
   assert (subscript >= 0);
-  assert (subscript < cat->n_cats_total - cat->n_vars);
+  assert (subscript < cat->n_cats_total);
 
-  return cat->reverse_variable_map[subscript];
+  return cat->reverse_variable_map_long[subscript];
 }
 
 
-/* Return the categorical variable corresponding to SUBSCRIPT */
-const struct variable *
-categoricals_get_variable_by_subscript (const struct categoricals *cat, int subscript)
+/* Return the interaction corresponding to SUBSCRIPT */
+const struct interaction *
+categoricals_get_interaction_by_subscript (const struct categoricals *cat, int subscript)
 {
-  int index = reverse_variable_lookup (cat, subscript);
+  int index = reverse_variable_lookup_short (cat, subscript);
 
-  return cat->vp[index].var;
+  return cat->iap[index].iact;
 }
 
-/* Return the value corresponding to SUBSCRIPT */
-const union value *
-categoricals_get_value_by_subscript (const struct categoricals *cat, int subscript)
+
+/* Return the case corresponding to SUBSCRIPT */
+static const struct ccase *
+categoricals_get_case_by_subscript (const struct categoricals *cat, int subscript)
 {
-  int vindex = reverse_variable_lookup (cat, subscript);
-  const struct var_params *vp = &cat->vp[vindex];
-  const struct value_node *vn = vp->reverse_value_map [subscript - vp->base_subscript];
+  int vindex = reverse_variable_lookup_short (cat, subscript);
+  const struct interact_params *vp = &cat->iap[vindex];
+  const struct interaction_value *vn = vp->reverse_interaction_value_map [subscript - vp->base_subscript_short];
+
+  if ( vn == NULL)
+    return NULL;
 
-  return &vn->value;
+  return vn->ccase;
 }
 
 
 double
 categoricals_get_weight_by_subscript (const struct categoricals *cat, int subscript)
 {
-  int vindex = reverse_variable_lookup (cat, subscript);
-  const struct var_params *vp = &cat->vp[vindex];
+  int vindex = reverse_variable_lookup_short (cat, subscript);
+  const struct interact_params *vp = &cat->iap[vindex];
 
   return vp->cc;
 }
@@ -401,13 +587,16 @@ categoricals_get_weight_by_subscript (const struct categoricals *cat, int subscr
 double
 categoricals_get_sum_by_subscript (const struct categoricals *cat, int subscript)
 {
-  int vindex = reverse_variable_lookup (cat, subscript);
-  const struct var_params *vp = &cat->vp[vindex];
+  int vindex = reverse_variable_lookup_short (cat, subscript);
+  const struct interact_params *vp = &cat->iap[vindex];
 
-  const struct value_node *vn = vp->reverse_value_map [subscript - vp->base_subscript];
-  return vn->cc;
-}
+  const struct interaction_value *iv = vp->reverse_interaction_value_map [subscript - vp->base_subscript_short];
+
+  if (iv == NULL)
+    return 0;
 
+  return iv->cc;
+}
 
 /* Returns unity if the value in case C at SUBSCRIPT is equal to the category
    for that subscript */
@@ -415,29 +604,41 @@ double
 categoricals_get_binary_by_subscript (const struct categoricals *cat, int subscript,
                                      const struct ccase *c)
 {
-  const struct variable *var = categoricals_get_variable_by_subscript (cat, subscript);
-  int width = var_get_width (var);
+  const struct interaction *iact = categoricals_get_interaction_by_subscript (cat, subscript);
+
+  const struct ccase *c2 =  categoricals_get_case_by_subscript (cat, subscript);
 
-  const union value *val = case_data (c, var);
+  if ( c2 == NULL)
+    return 0;
 
-  return value_equal (val, categoricals_get_value_by_subscript (cat, subscript), width);
+  return interaction_case_equal (iact, c, c2);
 }
 
 
 size_t
 categoricals_get_n_variables (const struct categoricals *cat)
 {
+  printf ("%s\n", __FUNCTION__);
   return cat->n_vars;
 }
 
+/* Return a case containing the set of values corresponding to SUBSCRIPT */
+const struct ccase *
+categoricals_get_case_by_category (const struct categoricals *cat, int subscript)
+{
+  int vindex = reverse_variable_lookup_long (cat, subscript);
+  const struct interact_params *vp = &cat->iap[vindex];
+  const struct interaction_value *vn = vp->reverse_interaction_value_map [subscript - vp->base_subscript_long];
 
+  return vn->ccase;
+}
 
 void *
-categoricals_get_user_data_by_subscript (const struct categoricals *cat, int subscript)
+categoricals_get_user_data_by_category (const struct categoricals *cat, int subscript)
 {
-  int vindex = reverse_variable_lookup (cat, subscript);
-  const struct var_params *vp = &cat->vp[vindex];
+  int vindex = reverse_variable_lookup_long (cat, subscript);
+  const struct interact_params *vp = &cat->iap[vindex];
 
-  const struct value_node *vn = vp->reverse_value_map [subscript - vp->base_subscript];
-  return vn->user_data;
+  const struct interaction_value *iv = vp->reverse_interaction_value_map [subscript - vp->base_subscript_long];
+  return iv->user_data;
 }
index 97cde65e74dda7f856674bb253eda6748d3ccb24..91767270de599218a6f8eddf46de65952672628f 100644 (file)
@@ -24,6 +24,7 @@
 struct categoricals;
 struct variable;
 struct ccase;
+struct interaction;
 
 union value ;
 
@@ -36,7 +37,7 @@ typedef void update_func (void *user_data,
 
 typedef void *user_data_create_func (void *aux1, void *aux2);
 
-struct categoricals *categoricals_create (const struct variable *const *v, size_t n_vars,
+struct categoricals *categoricals_create (struct interaction *const *, size_t n_int,
                                          const struct variable *wv, enum mv_class exclude,
                                          user_data_create_func *udf,
                                          update_func *update, void *aux1, void *aux2);
@@ -49,9 +50,14 @@ void categoricals_update (struct categoricals *cat, const struct ccase *c);
 /* Return the number of categories (distinct values) for variable N */
 size_t categoricals_n_count (const struct categoricals *cat, size_t n);
 
+size_t categoricals_df (const struct categoricals *cat, size_t n);
 
 /* Return the total number of categories */
-size_t categoricals_total (const struct categoricals *cat);
+size_t categoricals_n_total (const struct categoricals *cat);
+
+/* Return the total degrees of freedom */
+size_t categoricals_df_total (const struct categoricals *cat);
+
 
 /*
   Return the total number of variables which participated in these categoricals.
@@ -61,23 +67,37 @@ size_t categoricals_total (const struct categoricals *cat);
 */
 size_t categoricals_get_n_variables (const struct categoricals *cat);
 
-void categoricals_done (const struct categoricals *cat);
 
-const struct variable * categoricals_get_variable_by_subscript (const struct categoricals *cat, int subscript);
+/*
+  Must be called (once) before any call to the *_by_subscript or *_by_category
+  functions, but AFTER any calls to categoricals_update 
+*/
+void categoricals_done (const struct categoricals *cat);
 
-const union value * categoricals_get_value_by_subscript (const struct categoricals *cat, int subscript);
 
+/*
+  The *_by_subscript functions use the short map.
+  Their intended use is by covariance matrix routines, where normally 1 less than 
+  the total number of distinct values of each categorical variable should
+  be considered.
+ */
 double categoricals_get_weight_by_subscript (const struct categoricals *cat, int subscript);
+const struct interaction *categoricals_get_interaction_by_subscript (const struct categoricals *cat, int subscript);
 
 double categoricals_get_sum_by_subscript (const struct categoricals *cat, int subscript);
 
 double categoricals_get_binary_by_subscript (const struct categoricals *cat, int subscript,
                                             const struct ccase *c);
 
-void * categoricals_get_user_data_by_subscript (const struct categoricals *cat, int subscript);
 
+/* These use the long map.  Useful for descriptive statistics. */
+
+/* Return the value corresponding to the N'th category */
+const union value * categoricals_get_value_by_category (const struct categoricals *cat, int n);
 
+void * categoricals_get_user_data_by_category (const struct categoricals *cat, int category);
 
+const struct ccase * categoricals_get_case_by_category (const struct categoricals *cat, int subscript);
 
 
 #endif
index a7a5f131651963716ee0b0b5e8b8589a26579b2f..f64e89d1eb2ffbee673c2179e6d2e48b78d066f3 100644 (file)
@@ -25,6 +25,7 @@
 #include "libpspp/assertion.h"
 #include "libpspp/misc.h"
 #include "math/categoricals.h"
+#include "math/interaction.h"
 #include "math/moments.h"
 
 #include "gl/xalloc.h"
@@ -247,7 +248,7 @@ is_missing (const struct covariance *cov, int i, const struct ccase *c)
 {
   const struct variable *var = i < cov->n_vars ?
     cov->vars[i] : 
-    categoricals_get_variable_by_subscript (cov->categoricals, i - cov->n_vars);
+    categoricals_get_interaction_by_subscript (cov->categoricals, i - cov->n_vars)->vars[0];
 
   const union value *val = case_data (c, var);
 
@@ -346,11 +347,13 @@ covariance_accumulate_pass2 (struct covariance *cov, const struct ccase *c)
       assert (cov->state == 1);
       cov->state = 2;
 
+      if (cov->categoricals)
+       categoricals_done (cov->categoricals);
+
       cov->dim = cov->n_vars;
       
       if (cov->categoricals)
-       cov->dim += categoricals_total (cov->categoricals) 
-         - categoricals_get_n_variables (cov->categoricals);
+       cov->dim += categoricals_df_total (cov->categoricals);
 
       cov->n_cm = (cov->dim * (cov->dim - 1)  ) / 2;
       cov->cm = xcalloc (sizeof *cov->cm, cov->n_cm);
@@ -362,9 +365,6 @@ covariance_accumulate_pass2 (struct covariance *cov, const struct ccase *c)
          cov->moments[i] = resize_matrix (cov->moments[i], cov->dim);
        }
 
-      if (cov->categoricals)
-       categoricals_done (cov->categoricals);
-
       /* Populate the moments matrices with the categorical value elements */
       for (i = cov->n_vars; i < cov->dim; ++i)
        {
@@ -738,21 +738,4 @@ covariance_dim (const struct covariance * cov)
   return (cov->dim);
 }
 
-/*
-  Returns an array of variables corresponding to rows of the covariance matrix.
-  In other words, element i of the array is the variable corresponding to 
-  row (and column) i of the covariance matrix.
- */
-void
-covariance_get_var_indices (const struct covariance *cov, struct variable **vars)
-{
-  int i;
-  for (i = 0; i < cov->n_vars; i++)
-    {
-      vars[i] = cov->vars[i];
-    }
-  for (i = cov->n_vars; i < cov->dim; i++)
-    {
-      vars[i] = categoricals_get_variable_by_subscript (cov->categoricals, i - cov->n_vars);
-    }
-}
+
index 6ec645b7e27009df8b195aa96ef32604795e46e8..ed5b3ee73426951d0084eb5df20f8492db541cb7 100644 (file)
@@ -47,7 +47,6 @@ void covariance_destroy (struct covariance *cov);
 const gsl_matrix *covariance_moments (const struct covariance *cov, int m);
 
 const struct categoricals * covariance_get_categoricals (const struct covariance *cov);
-
-void covariance_get_var_indices (const struct covariance *cov, struct variable **vars);
 size_t covariance_dim (const struct covariance * cov);
+
 #endif
diff --git a/src/math/group-proc.h b/src/math/group-proc.h
deleted file mode 100644 (file)
index fe35acc..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/* PSPP - a program for statistical analysis.
-   Copyright (C) 2004 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/>. */
-
-#ifndef GROUP_DATA_H
-#define GROUP_DATA_H
-
-#include "group.h"
-
-/* private data for commands dealing with grouped data*/
-struct group_proc
-{
-  /* Stats for the `universal group'  (ie the totals) */
-  struct group_statistics ugs;
-
-  /* The number of groups */
-  int n_groups;
-
-  /* The levene statistic */
-  double levene ;
-
-  /* A hash of group statistics keyed by the value of the
-     independent variable */
-  struct hsh_table *group_hash;
-
-  /* Mean square error */
-  double mse ;
-
-};
-
-struct variable;
-struct group_proc *group_proc_get (const struct variable *);
-
-#endif
diff --git a/src/math/group.c b/src/math/group.c
deleted file mode 100644 (file)
index 6f86f87..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2009, 2011 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 "math/group.h"
-
-#include <stdlib.h>
-
-#include "data/variable.h"
-#include "libpspp/compiler.h"
-#include "libpspp/hash.h"
-#include "libpspp/misc.h"
-#include "libpspp/str.h"
-#include "math/group-proc.h"
-
-#include "gl/xalloc.h"
-
-void
-free_group (struct group_statistics *v, void *aux UNUSED)
-{
-  free(v);
-}
-
-static void
-group_proc_dtor (struct variable *var)
-{
-  struct group_proc *group = var_detach_aux (var);
-
-  hsh_destroy (group->group_hash);
-  free (group);
-}
-
-struct group_proc *
-group_proc_get (const struct variable *v)
-{
-  /* This is not ideal, obviously. */
-  struct group_proc *group = var_get_aux (v);
-  if (group == NULL)
-    {
-      group = xzalloc (sizeof *group);
-      var_attach_aux (v, group, group_proc_dtor);
-    }
-  return group;
-}
diff --git a/src/math/group.h b/src/math/group.h
deleted file mode 100644 (file)
index 1e0b267..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/* PSPP - a program for statistical analysis.
-   Copyright (C) 2004, 2011 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/>. */
-
-
-#ifndef GROUP_H
-#define GROUP_H
-
-#include "data/value.h"
-
-/* Statistics for grouped data */
-struct group_statistics
-  {
-    /* The value of the independent variable for this group */
-    union value id;
-
-    /* The arithmetic mean */
-    double mean;
-
-    /* Population std. deviation */
-    double std_dev;
-
-    /* Sample std. deviation */
-    double s_std_dev;
-
-    /* count */
-    double n;
-
-    double sum;
-
-    /* Sum of squares */
-    double ssq;
-
-    /* Std Err of Mean */
-    double se_mean;
-
-    /* Sum of differences */
-    double sum_diff;
-
-    /* Mean of differences */
-    double mean_diff ;
-
-    /* Running total of the Levene for this group */
-    double lz_total;
-
-    /* Group mean of Levene */
-    double lz_mean;
-
-
-    /* min and max values */
-    double minimum ;
-    double maximum ;
-  };
-
-
-struct variable ;
-
-void  free_group (struct group_statistics *v, void *aux);
-
-#endif
index 87f4836da23479ced8fa9a2069841ada800408d9..d24166d4379b18bf7e7b84c976b6cd4ad2aa4ad8 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2011 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
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-/*
-  An interaction is a structure containing a "product" of other
-  variables. The variables can be either categorical or numeric.
-  If the variables are all numeric, the interaction is just the
-  scalar product. If any of the variables are categorical, their
-  product is a vector containing 0's in all but one entry. This entry
-  is found by combining the vectors corresponding to the variables'
-  OBS_VALS member. If there are K categorical variables, each with
-  N_1, N_2, ..., N_K categories, then the interaction will have
-  N_1 * N_2 * N_3 *...* N_K - 1 entries.
-
-  When using these functions, make sure the orders of variables and
-  values match when appropriate.
- */
-
 #include <config.h>
 
-#include "math/interaction.h"
-
-#include <assert.h>
-#include <string.h>
-#include <unistr.h>
+#include "data/case.h"
+#include "interaction.h"
 
-#include "data/dictionary.h"
 #include "data/value.h"
 #include "data/variable.h"
+#include "libpspp/str.h"
 
 #include "gl/xalloc.h"
 
-struct interaction_variable
-{
-  int n_vars;
-  const struct variable **members;
-  struct variable *intr;
-  size_t n_alpha;
-};
+#include <stdio.h>
 
-struct interaction_value
-{
-  const struct interaction_variable *intr;
-  union value val; /* Concatenation of the string values in this
-                      interaction's value, or the product of a bunch
-                      of numeric values for a purely numeric
-                      interaction.
-                   */
-  double f; /* Product of the numerical values in this interaction's value. */
-};
 
 /*
-  An interaction_variable has type alpha if any of members have type
-  alpha. Otherwise, its type is numeric.
- */
-struct interaction_variable *
-interaction_variable_create (const struct variable **vars, int n_vars)
-{
-  struct interaction_variable *result = NULL;
-  size_t i;
+  An interaction is a structure containing a "product" of other
+  variables. The variables can be either string or numeric.
 
-  if (n_vars > 0)
-    {
-      int width = 0;
+  Interaction is commutative.  That means, that from a mathematical point of
+  view,  the order of the variables is irrelevant.  However, for display
+  purposes, and for matching with an interaction's value the order is 
+  pertinent.
+  
+  Therefore, when using these functions, make sure the orders of variables 
+  and values match when appropriate.
+*/
 
-      result = xmalloc (sizeof (*result));
-      result->n_alpha = 0;
-      result->members = xnmalloc (n_vars, sizeof (*result->members));
-      result->n_vars = n_vars;
-      for (i = 0; i < n_vars; i++)
-       {
-         result->members[i] = vars[i];
-         if (var_is_alpha (vars[i]))
-           {
-             result->n_alpha++;
-             width += var_get_width (vars[i]);
-           }
-       }
-      result->intr = dict_create_internal_var (0, width);
-    }
 
-  return result;
-}
-void interaction_variable_destroy (struct interaction_variable *iv)
-{
-  dict_destroy_internal_var (iv->intr);
-  free (iv->members);
-  free (iv);
-}
 
-/*
-  Get one of the member variables.
- */
-const struct variable *
-interaction_get_member (const struct interaction_variable *iv, size_t i)
+struct interaction *
+interaction_create (const struct variable *v)
 {
-  return iv->members[i];
+  struct interaction  *i = xmalloc (sizeof *i);
+  i->vars = xmalloc (sizeof *i->vars);
+  i->n_vars = 0;
+  if ( v )
+    {
+      i->vars[0] = v;
+      i->n_vars = 1;
+    }
+  return i;
 }
 
-size_t
-interaction_get_n_vars (const struct interaction_variable *iv)
+void
+interaction_destroy (struct interaction *i)
 {
-  return (iv == NULL) ? 0 : iv->n_vars;
+  free (i->vars);
+  free (i);
 }
 
-size_t
-interaction_get_n_alpha (const struct interaction_variable *iv)
+void
+interaction_add_variable (struct interaction *i, const struct variable *v)
 {
-  return iv->n_alpha;
+  i->vars = xrealloc (i->vars, sizeof (*i->vars) * ++i->n_vars);
+  i->vars[i->n_vars - 1] = v;
 }
 
-size_t
-interaction_get_n_numeric (const struct interaction_variable *iv)
-{
-  return (interaction_get_n_vars (iv) - interaction_get_n_alpha (iv));
-}
 
-/*
-  Get the interaction variable itself.
- */
-const struct variable *
-interaction_get_variable (const struct interaction_variable *iv)
+void
+interaction_dump (const struct interaction *i)
 {
-  return iv->intr;
-}
-/*
-  Given list of values, compute the value of the corresponding
-  interaction.  This "value" is not stored as the typical vector of
-  0's and one double, but rather the string values are concatenated to
-  make one big string value, and the numerical values are multiplied
-  together to give the non-zero entry of the corresponding vector.
- */
-struct interaction_value *
-interaction_value_create (const struct interaction_variable *var, const union value **vals)
-{
-  struct interaction_value *result = NULL;
-  
-  if (var != NULL)
+  int v = 0;
+  printf ("%s", var_get_name (i->vars[v]));
+  for (v = 1; v < i->n_vars; ++v)
     {
-      size_t i;
-      int val_width = var_get_width (interaction_get_variable (var));
-      int offset = 0;
-      size_t n_vars = interaction_get_n_vars (var);
-
-      result = xmalloc (sizeof (*result));
-      result->intr = var;
-
-      value_init (&result->val, val_width);
-
-      result->f = 1.0;
-      for (i = 0; i < n_vars; i++)
-       {
-          const struct variable *member = interaction_get_member (var, i);
-
-         if (var_is_value_missing (member, vals[i], MV_ANY))
-           {
-             value_set_missing (&result->val, val_width);
-             result->f = SYSMIS;
-             break;
-           }
-         else
-           {
-             if (var_is_alpha (var->members[i]))
-               {
-                 uint8_t *val = value_str_rw (&result->val, val_width);
-                  int w = var_get_width (var->members[i]);
-                  u8_cpy (val + offset, value_str (vals[i], w), w);
-                  offset += w;
-               }
-             else if (var_is_numeric (var->members[i]))
-               {
-                 result->f *= vals[i]->f;
-               }
-           }
-       }
-      if (interaction_get_n_alpha (var) == 0)
-       {
-         /*
-           If there are no categorical variables, then the
-           interaction consists of only numeric data. In this case,
-           code that uses this interaction_value will see the union
-           member as the numeric value. If we were to store that
-           numeric value in result->f as well, the calling code may
-           inadvertently square this value by multiplying by
-           result->val->f. Such multiplication would be correct for an
-           interaction consisting of both categorical and numeric
-           data, but a mistake for purely numerical interactions. To
-           avoid the error, we set result->f to 1.0 for numeric
-           interactions.
-          */
-         result->val.f = result->f;
-         result->f = 1.0;
-       }
+      printf (" * %s", var_get_name (i->vars[v]));
     }
-  return result;
+  printf ("\n");
 }
 
-const union value *
-interaction_value_get (const struct interaction_value *val)
-{
-  return &val->val;
-}
+/* Appends STR with a representation of the interaction, suitable for user
+   display.
 
-/*
-  Returns the numeric value of the non-zero entry for the vector
-  corresponding to this interaction.  Do not use this function to get
-  the numeric value of a purely numeric interaction. Instead, use the
-  union value * returned by interaction_value_get.
- */
-double 
-interaction_value_get_nonzero_entry (const struct interaction_value *val)
+   STR must have been initialised prior to calling this function.
+*/
+void
+interaction_to_string (const struct interaction *iact, struct string *str)
 {
-  if (val != NULL)
-    return val->f;
-  return 1.0;
+  int v = 0;
+  ds_put_cstr (str, var_to_string (iact->vars[v]));
+  for (v = 1; v < iact->n_vars; ++v)
+    {
+      ds_put_cstr (str, " * ");
+      ds_put_cstr (str, var_to_string (iact->vars[v]));
+    }
 }
 
-void 
-interaction_value_destroy (struct interaction_value *val)
+unsigned int
+interaction_case_hash (const struct interaction *iact, const struct ccase *c)
 {
-  if (val != NULL)
+  int i;
+  size_t hash = 0;
+  for (i = 0; i < iact->n_vars; ++i)
     {
-      int val_width = var_get_width (interaction_get_variable (val->intr));
-
-      value_destroy (&val->val, val_width);
-      free (val);
+      const struct variable *var = iact->vars[i];
+      const union value *val = case_data (c, var);
+      hash = value_hash (val, var_get_width (var), hash);
     }
+  return hash;
 }
 
-/*
-  Return a value from a variable that is an interaction. 
- */
-struct interaction_value *
-interaction_case_data (const struct ccase *ccase, const struct interaction_variable *iv)
+bool
+interaction_case_equal (const struct interaction *iact, const struct ccase *c1, const struct ccase *c2)
 {
-  size_t i;
-  size_t n_vars;
-  const struct variable *member;
-  const union value **vals = NULL;
+  int i;
+  bool same = true;
 
-  n_vars = interaction_get_n_vars (iv);
-  vals = xnmalloc (n_vars, sizeof (*vals));
-
-  for (i = 0; i < n_vars; i++)
+  for (i = 0; i < iact->n_vars; ++i)
+    {
+      const struct variable *var = iact->vars[i];
+      if ( ! value_equal (case_data (c1, var), case_data (c2, var), var_get_width (var)))
        {
-         member = interaction_get_member (iv, i);
-         vals[i] = case_data (ccase, member);
+         same = false;
+         break;
        }
+    }
 
-  return interaction_value_create (iv, vals);
+  return same;
 }
 
+
+int
+interaction_case_cmp_3way (const struct interaction *iact, const struct ccase *c1, const struct ccase *c2)
+{
+  int i;
+  int result = 0;
+
+  for (i = 0; i < iact->n_vars; ++i)
+    {
+      const struct variable *var = iact->vars[i];
+      result = value_compare_3way (case_data (c1, var), case_data (c2, var), var_get_width (var));
+      if (result != 0)
+       break;
+    }
+
+  return result;
+}
+
+
 bool
-is_interaction (const struct variable *var, const struct interaction_variable **iv, size_t n_intr)
+interaction_case_is_missing (const struct interaction *iact, const struct ccase *c, enum mv_class exclude)
 {
-  size_t i;
-  const struct variable *intr;
-  
-  for (i = 0; i < n_intr; i++)
+  int i;
+  bool missing = false;
+
+  for (i = 0; i < iact->n_vars; ++i)
     {
-      intr = interaction_get_variable (iv[i]);
-      if (intr == var)
+      if ( var_is_value_missing (iact->vars[i], case_data (c, iact->vars[i]), exclude))
        {
-         return true;
+         missing = true;
+         break;
        }
     }
-  return false;
+
+  return missing;
 }
-  
+
index 13b13690f9360114826b2deda1597f4c9e3a2ae1..cd38ae226ea81b6e288c80c6a4aa30aa03e8e066 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2009, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2011 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
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-#ifndef INTERACTION_H
-#define INTERACTION_H
-
-#include "data/case.h"
-
-struct interaction_variable;
-struct interaction_value;
-
-struct interaction_variable * interaction_variable_create (const struct variable **, int);
-void interaction_variable_destroy (struct interaction_variable *);
-struct interaction_value * interaction_value_create (const struct interaction_variable *, const union value **);
-void interaction_value_destroy (struct interaction_value *);
-size_t interaction_variable_get_n_vars (const struct interaction_variable *);
-double interaction_value_get_nonzero_entry (const struct interaction_value *);
-const union value *interaction_value_get (const struct interaction_value *);
-const struct variable * interaction_get_variable (const struct interaction_variable *);
-size_t interaction_get_n_numeric (const struct interaction_variable *);
-size_t interaction_get_n_alpha (const struct interaction_variable *);
-size_t interaction_get_n_vars (const struct interaction_variable *);
-const struct variable * interaction_get_member (const struct interaction_variable *, size_t);
-bool is_interaction (const struct variable *, const struct interaction_variable **, size_t);
-struct interaction_value *
-interaction_case_data (const struct ccase *, const struct interaction_variable *);
-double interaction_value_get_nonzero_entry (const struct interaction_value *);
+
+#ifndef _INTERACTION_H__
+#define _INTERACTION_H__ 1
+
+#include <stdbool.h>
+#include "data/missing-values.h"
+
+struct interaction;
+struct variable;
+struct string;
+
+#include <stddef.h>
+struct interaction
+{
+  size_t n_vars;
+  const struct variable **vars;
+};
+
+struct interaction * interaction_create (const struct variable *);
+void interaction_destroy (struct interaction *);
+void interaction_add_variable (struct interaction *, const struct variable *);
+void interaction_dump (const struct interaction *);
+void interaction_to_string (const struct interaction *iact, struct string *str);
+
+
+struct ccase;
+unsigned int interaction_case_hash (const struct interaction *, const struct ccase *);
+bool interaction_case_equal (const struct interaction *, const struct ccase *, const struct ccase *);
+bool interaction_case_is_missing (const struct interaction *, const struct ccase *, enum mv_class);
+int interaction_case_cmp_3way (const struct interaction *, const struct ccase *, const struct ccase *);
+
+
 #endif
index 13fad93e52107ebe5a16ca826fbbedb06dbf8928..fe04d294e1acfbf214dadea6a53717ccc9a37646 100644 (file)
 
 #include <config.h>
 
-#include "math/levene.h"
-
+#include "levene.h"
 #include <math.h>
 
-#include "data/case.h"
-#include "data/casereader.h"
-#include "data/variable.h"
-#include "libpspp/hmap.h"
 #include "libpspp/misc.h"
+#include "libpspp/hmap.h"
+#include "data/value.h"
+
+#include <gl/xalloc.h>
+#include <assert.h>
 
 struct lev
 {
   struct hmap_node node;
   union value group;
-  int width;
 
   double t_bar;
   double z_mean;
   double n;
 };
 
+typedef unsigned int hash_func (const struct levene *, const union value *v);
+typedef bool cmp_func (const struct levene *, const union value *v0, const union value *v1);
+
+struct levene
+{
+  /* Width of the categorical variable */
+  int gvw ;
+
+  /* The value deviding the the groups. Valid only for dichotomous categorical variable.*/
+  const union value *cutpoint;
+
+
+  /* A hashtable of struct lev objects indexed by union value */
+  struct hmap hmap;
+
+  hash_func *hash;
+  cmp_func *cmp;
+
+
+  /* A state variable indicating how many passes have been done */
+  int pass;
+
+  double grand_n;
+  double z_grand_mean;
+
+  double denominator;
+};
+
+
+static unsigned int
+unique_hash (const struct levene *nl, const union value *val)
+{
+  return value_hash (val, nl->gvw, 0);
+}
+
+static bool
+unique_cmp (const struct levene *nl, const union value *val0, const union value *val1)
+{
+  return value_equal (val0, val1, nl->gvw);
+}
+
+static unsigned int
+cutpoint_hash (const struct levene *nl, const union value *val)
+{
+  int x = value_compare_3way (val, nl->cutpoint, nl->gvw);
+
+  return (x < 0);
+}
+
+static bool
+cutpoint_cmp (const struct levene *nl, const union value *val0, const union value *val1)
+{
+  int x = value_compare_3way (val0, nl->cutpoint, nl->gvw);
+
+  int y = value_compare_3way (val1, nl->cutpoint, nl->gvw);
+
+  if ( x == 0) x = 1;
+  if ( y == 0) y = 1;
+
+  return ( x == y);
+}
+
+
 
 static struct lev *
-find_group (struct hmap *map, const union value *target, int width)
+find_group (const struct levene *nl, const union value *target)
 {
   struct lev *l = NULL;
-  unsigned int hash = value_hash (target, width, 0);
-  HMAP_FOR_EACH_WITH_HASH (l, struct lev, node, hash, map)
+
+  HMAP_FOR_EACH_WITH_HASH (l, struct lev, node, nl->hash (nl, target), &nl->hmap)
     {
-      if (value_equal (&l->group, target, width))
+      if (nl->cmp (nl, &l->group, target))
        break;
       l = NULL;
     }
-
   return l;
 }
 
 
-double
-levene (struct casereader *rx, const struct variable *gvar,
-       const struct variable *var, const struct variable *wv,
-       enum mv_class exclude)
+struct levene *
+levene_create (int indep_width, const union value *cutpoint)
 {
-  double numerator = 0.0;
-  double denominator = 0.0;
-  int n_groups = 0;
-  double z_grand_mean = 0.0;
-  double grand_n = 0.0;
+  struct levene *nl = xzalloc (sizeof *nl);
+
+  hmap_init (&nl->hmap);
+
+  nl->gvw = indep_width;
+  nl->cutpoint = cutpoint;
 
-  struct hmap map = HMAP_INITIALIZER (map);
+  nl->hash  = cutpoint ? cutpoint_hash : unique_hash;
+  nl->cmp   = cutpoint ? cutpoint_cmp : unique_cmp;
+
+  return nl;
+}
 
-  struct ccase *c;
-  struct casereader *r = casereader_clone (rx);
 
-  for (; (c = casereader_read (r)) != NULL; case_unref (c))
+/* Data accumulation. First pass */
+void 
+levene_pass_one (struct levene *nl, double value, double weight, const union value *gv)
+{
+  struct lev *lev = find_group (nl, gv);
+
+  if ( nl->pass == 0 ) 
+    {
+      nl->pass = 1;
+    }
+  assert (nl->pass == 1);
+
+  if ( NULL == lev)
     {
-      struct lev *l = NULL;
-      const union value *target = case_data (c, gvar);
-      int width = var_get_width (gvar);
-      unsigned int hash = value_hash (target, width, 0);
-      const double x = case_data (c, var)->f;
-      const double weight = wv ? case_data (c, wv)->f : 1.0;
-
-      if (var_is_value_missing (var, case_data (c, var), exclude))
-       continue;
-
-      l = find_group (&map, target, width);
-      
-      if (l == NULL)
-       {
-         l = xzalloc (sizeof *l);
-         value_clone (&l->group, target, width);
-         hmap_insert (&map, &l->node, hash);
-       }
-
-      l->n += weight;
-      l->t_bar += x * weight;
-      grand_n += weight;
+      struct lev *l = xzalloc (sizeof *l);
+      value_clone (&l->group, gv, nl->gvw);
+      hmap_insert (&nl->hmap, &l->node, nl->hash (nl, &l->group));
+      lev = l;
     }
-  casereader_destroy (r);
 
-  {
-    struct lev *l;
-    HMAP_FOR_EACH (l, struct lev, node, &map)
+  lev->n += weight;
+  lev->t_bar += value * weight;
+
+  nl->grand_n += weight;
+}
+
+/* Data accumulation. Second pass */
+void 
+levene_pass_two (struct levene *nl, double value, double weight, const union value *gv)
+{
+  struct lev *lev = NULL;
+
+  if ( nl->pass == 1 )
+    {
+      struct lev *next;
+      struct lev *l;
+
+      nl->pass = 2;
+
+      HMAP_FOR_EACH_SAFE (l, next, struct lev, node, &nl->hmap)
       {
        l->t_bar /= l->n;
       }
-  }
+    }
+  assert (nl->pass == 2);
 
-  n_groups = hmap_count (&map);
+  lev = find_group (nl, gv);
 
-  r = casereader_clone (rx);
-  for (; (c = casereader_read (r)) != NULL; case_unref (c))
+  lev->z_mean += fabs (value - lev->t_bar) * weight;
+  nl->z_grand_mean += fabs (value - lev->t_bar) * weight;
+}
+
+/* Data accumulation. Third pass */
+void 
+levene_pass_three (struct levene *nl, double value, double weight, const union value *gv)
+{
+  double z;
+  struct lev *lev = NULL;
+
+  if ( nl->pass == 2 )
     {
-      struct lev *l = NULL;
-      const union value *target = case_data (c, gvar);
-      int width = var_get_width (gvar);
-      const double x = case_data (c, var)->f;
-      const double weight = wv ? case_data (c, wv)->f : 1.0;
-
-      if (var_is_value_missing (var, case_data (c, var), exclude))
-       continue;
-
-      l = find_group (&map, target, width);
-      assert (l);
-      
-      l->z_mean += fabs (x - l->t_bar) * weight;
-      z_grand_mean += fabs (x - l->t_bar) * weight;
-    }
-  casereader_destroy (r);
+      struct lev *next;
+      struct lev *l;
+
+      nl->pass = 3;
 
-  {
-    struct lev *l;
-    HMAP_FOR_EACH (l, struct lev, node, &map)
+      HMAP_FOR_EACH_SAFE (l, next, struct lev, node, &nl->hmap)
       {
        l->z_mean /= l->n;
       }
+
+      nl->z_grand_mean /= nl->grand_n;
   }
 
-  z_grand_mean /= grand_n;
+  assert (nl->pass == 3);
+  lev = find_group (nl, gv);
+
+  z = fabs (value - lev->t_bar);
+  nl->denominator += pow2 (z - lev->z_mean) * weight;
+}
+
 
-  r = casereader_clone (rx);
-  for (; (c = casereader_read (r)) != NULL; case_unref (c))
+/* Return the value of the levene statistic */
+double
+levene_calculate (struct levene *nl)
+{
+  struct lev *next;
+  struct lev *l;
+
+  double numerator = 0.0;
+  double nn = 0.0;
+  if ( nl->pass == 3 )
     {
-      double z;
-      struct lev *l;
-      const union value *target = case_data (c, gvar);
-      int width = var_get_width (gvar);
-      const double x = case_data (c, var)->f;
-      const double weight = wv ? case_data (c, wv)->f : 1.0;
+      nl->pass = 4;
+    }
 
-      if (var_is_value_missing (var, case_data (c, var), exclude))
-       continue;
+  assert (nl->pass == 4);
 
-      l = find_group (&map, target, width);
-      assert (l);
+  nl->denominator *= hmap_count (&nl->hmap) - 1;
 
-      z = fabs (x - l->t_bar);
-      denominator += pow2 (z - l->z_mean) * weight;
+  HMAP_FOR_EACH_SAFE (l, next, struct lev, node, &nl->hmap)
+    {
+      numerator += l->n * pow2 (l->z_mean - nl->z_grand_mean);
+      nn += l->n;
     }
-  casereader_destroy (r);
 
-  denominator *= n_groups - 1;
+  numerator *= nn - hmap_count (&nl->hmap);
+    
+  return numerator / nl->denominator;
+}
 
-  {
-    double grand_n = 0.0;
-    struct lev *next;
-    struct lev *l;
-    HMAP_FOR_EACH_SAFE (l, next, struct lev, node, &map)
-      {
-       numerator += l->n * pow2 (l->z_mean - z_grand_mean);
-       grand_n += l->n;
+void
+levene_destroy (struct levene *nl)
+{
+  struct lev *next;
+  struct lev *l;
 
-       /* We don't need these anymore */
-       free (l);
-      }
-    numerator *= grand_n - n_groups ;
-    hmap_destroy (&map);
-  }
+  HMAP_FOR_EACH_SAFE (l, next, struct lev, node, &nl->hmap)
+    {
+      value_destroy (&l->group, nl->gvw);
+      free (l);
+    }
 
-  return numerator/ denominator;
+  hmap_destroy (&nl->hmap);
+  free (nl);
 }
index c5e8bc3b4e9a15a49bc97d6837bb680cc06ceb4b..4351ee092a127db7c1e9a82d562dc94eec1c6e1c 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2004 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2011 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
 #if !levene_h
 #define levene_h 1
 
-struct casereader;
-struct variable;
+struct nl;
 
+union value;
 
-enum mv_class;
+struct levene *levene_create (int indep_width, const union value *cutpoint);
 
-double
-levene (struct casereader *rx, const struct variable *gvar,
-       const struct variable *var, const struct variable *wv,  enum mv_class exclude );
+void levene_pass_one (struct levene *, double value, double weight, const union value *gv);
+void levene_pass_two (struct levene *, double value, double weight, const union value *gv);
+void levene_pass_three (struct levene *, double value, double weight, const union value *gv);
 
+double levene_calculate (struct levene*);
+
+void levene_destroy (struct levene*);
 
 #endif
index 6f9b149e82a8d7fe4ec83b208dc9ac68d1d51df0..78173e3ef2a45da602c8c39bc4af0a9638622e54 100644 (file)
@@ -68,7 +68,7 @@ src_output_liboutput_la_SOURCES += \
        src/output/charts/roc-chart-cairo.c \
        src/output/charts/scree-cairo.c
 endif
-if ODT_SUPPORT
+if ODF_WRITE_SUPPORT
 src_output_liboutput_la_SOURCES += src/output/odt.c
 endif
 
index c0a525edae2f4963c3b34067c8c8f474b5b1a017..5c5c8648864fd0866ed1312b405c803f68294497 100644 (file)
@@ -235,7 +235,7 @@ extern const struct output_driver_factory txt_driver_factory;
 extern const struct output_driver_factory list_driver_factory;
 extern const struct output_driver_factory html_driver_factory;
 extern const struct output_driver_factory csv_driver_factory;
-#ifdef ODT_SUPPORT
+#ifdef ODF_WRITE_SUPPORT
 extern const struct output_driver_factory odt_driver_factory;
 #endif
 #ifdef HAVE_CAIRO
@@ -250,7 +250,7 @@ static const struct output_driver_factory *factories[] =
     &list_driver_factory,
     &html_driver_factory,
     &csv_driver_factory,
-#ifdef ODT_SUPPORT
+#ifdef ODF_WRITE_SUPPORT
     &odt_driver_factory,
 #endif
 #ifdef HAVE_CAIRO
index a4fe9e24e65eae7d82b9f7fa984cca010b2dfc0e..8332b85d98ecb51e1ad3849eb6072eab5ceec130 100644 (file)
@@ -815,7 +815,7 @@ render_page_get_size (const struct render_page *page, enum table_axis axis)
 \f
 /* Drawing render_pages. */
 
-static enum render_line_style
+static inline enum render_line_style
 get_rule (const struct render_page *page, enum table_axis axis,
           const int d[TABLE_N_AXES])
 {
index 207bbd4d8d884826e08464a73d6524504aaeb0b3..2ebb844ed5422273713dff074c04c445583b4649 100644 (file)
@@ -164,6 +164,7 @@ choose_filename (struct aggregate *fd)
                                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                                           GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
                                                           NULL);
+  g_object_set (dialog, "local-only", FALSE, NULL);
 
   gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
 
@@ -533,7 +534,7 @@ aggregate_dialog (PsppireDataWindow *dw)
 
     column = gtk_tree_view_get_column (PSPPIRE_ACR (fd.summary_acr)->tv, 0);
 
-    l = gtk_tree_view_column_get_cell_renderers (column);
+    l = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
 
     cell_renderer = l->data;
 
index 8cbcf2af8ebc64892ef2888edacc46142b13ba78..a43005655599a92dd72d0e15fa70cf4e2a865b55 100644 (file)
                             <property name="label" translatable="yes">_Break variable(s)</property>
                             <property name="use_markup">True</property>
                             <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">psppire-var-view1</property>
                           </object>
                         </child>
                       </object>
index 6097d16b82d3a2d9dcec1b46963d4cf06330a337..2c8e02b6ff364be572f90929b1d45727d8431e0a 100644 (file)
@@ -4,9 +4,11 @@ include $(top_srcdir)/src/ui/gui/sheet/automake.mk
 
 UI_FILES = \
        src/ui/gui/aggregate.ui \
+       src/ui/gui/autorecode.ui \
        src/ui/gui/binomial.ui \
        src/ui/gui/compute.ui \
        src/ui/gui/correlation.ui \
+       src/ui/gui/count.ui \
        src/ui/gui/crosstabs.ui \
        src/ui/gui/chi-square.ui \
        src/ui/gui/descriptives.ui \
@@ -16,10 +18,14 @@ UI_FILES = \
        src/ui/gui/factor.ui \
        src/ui/gui/find.ui \
        src/ui/gui/frequencies.ui \
+       src/ui/gui/k-means.ui \
        src/ui/gui/k-related.ui \
+       src/ui/gui/ks-one-sample.ui \
        src/ui/gui/oneway.ui \
+       src/ui/gui/paired-samples.ui \
        src/ui/gui/psppire.ui \
        src/ui/gui/rank.ui \
+       src/ui/gui/runs.ui \
        src/ui/gui/sort.ui \
        src/ui/gui/split-file.ui \
        src/ui/gui/recode.ui \
@@ -83,7 +89,7 @@ install-lang:
 install-icons:
        for size in 16x16 ; do \
          $(MKDIR_P) $(themedir)/$$size/$(context) ; \
-          $(INSTALL) $(top_srcdir)/src/ui/gui/psppicon.png $(themedir)/$$size/$(context) ; \
+          $(INSTALL) $(top_srcdir)/src/ui/gui/icons/$$size/* $(themedir)/$$size/$(context) ; \
        done 
        gtk-update-icon-cache --ignore-theme-index $(themedir)
 
@@ -124,7 +130,11 @@ src_ui_gui_psppire_SOURCES = \
        src/ui/gui/psppire-buttonbox.c \
        src/ui/gui/psppire-hbuttonbox.c \
        src/ui/gui/psppire-vbuttonbox.c \
+       src/ui/gui/psppire-scanf.c \
+       src/ui/gui/psppire-scanf.h \
        src/ui/gui/psppire-acr.c \
+       src/ui/gui/autorecode-dialog.c \
+       src/ui/gui/autorecode-dialog.h \
        src/ui/gui/aggregate-dialog.c \
        src/ui/gui/aggregate-dialog.h \
        src/ui/gui/binomial-dialog.c \
@@ -139,6 +149,8 @@ src_ui_gui_psppire_SOURCES = \
        src/ui/gui/chi-square-dialog.h \
        src/ui/gui/correlation-dialog.c \
        src/ui/gui/correlation-dialog.h \
+       src/ui/gui/count-dialog.c \
+       src/ui/gui/count-dialog.h \
        src/ui/gui/crosstabs-dialog.c \
        src/ui/gui/crosstabs-dialog.h \
        src/ui/gui/customentry.c \
@@ -169,11 +181,17 @@ src_ui_gui_psppire_SOURCES = \
        src/ui/gui/helper.h \
        src/ui/gui/k-related-dialog.c \
        src/ui/gui/k-related-dialog.h \
+       src/ui/gui/k-means-dialog.c \
+       src/ui/gui/k-means-dialog.h \
+       src/ui/gui/ks-one-sample-dialog.c \
+       src/ui/gui/ks-one-sample-dialog.h \
        src/ui/gui/main.c \
        src/ui/gui/missing-val-dialog.c \
        src/ui/gui/missing-val-dialog.h \
         src/ui/gui/oneway-anova-dialog.c \
         src/ui/gui/oneway-anova-dialog.h \
+       src/ui/gui/paired-dialog.c \
+       src/ui/gui/paired-dialog.h \
        src/ui/gui/psppire.c \
        src/ui/gui/psppire.h \
        src/ui/gui/psppire-acr.h \
@@ -204,6 +222,8 @@ src_ui_gui_psppire_SOURCES = \
        src/ui/gui/psppire-select-dest.h \
        src/ui/gui/psppire-syntax-window.c \
        src/ui/gui/psppire-syntax-window.h \
+       src/ui/gui/psppire-val-chooser.c \
+       src/ui/gui/psppire-val-chooser.h \
        src/ui/gui/psppire-var-ptr.c \
        src/ui/gui/psppire-var-ptr.h \
        src/ui/gui/psppire-var-sheet.c \
@@ -225,6 +245,8 @@ src_ui_gui_psppire_SOURCES = \
        src/ui/gui/reliability-dialog.h \
        src/ui/gui/roc-dialog.c \
        src/ui/gui/roc-dialog.h \
+       src/ui/gui/runs-dialog.c \
+       src/ui/gui/runs-dialog.h \
        src/ui/gui/select-cases-dialog.c \
        src/ui/gui/select-cases-dialog.h \
        src/ui/gui/sort-cases-dialog.c \
@@ -243,6 +265,8 @@ src_ui_gui_psppire_SOURCES = \
        src/ui/gui/t-test-options.h \
        src/ui/gui/t-test-paired-samples.c \
        src/ui/gui/t-test-paired-samples.h \
+       src/ui/gui/npar-two-sample-related.c \
+       src/ui/gui/npar-two-sample-related.h \
        src/ui/gui/val-labs-dialog.c \
        src/ui/gui/val-labs-dialog.h \
        src/ui/gui/var-display.c \
diff --git a/src/ui/gui/autorecode-dialog.c b/src/ui/gui/autorecode-dialog.c
new file mode 100644 (file)
index 0000000..6780bc7
--- /dev/null
@@ -0,0 +1,404 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  Free Software Foundation
+
+   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 "dialog-common.h"
+#include "autorecode-dialog.h"
+#include "psppire-selector.h"
+#include "psppire-dictview.h"
+#include "psppire-var-ptr.h"
+#include "psppire-dialog.h"
+
+#include "psppire-data-window.h"
+#include "psppire-var-view.h"
+
+#include "executor.h"
+#include "helper.h"
+
+#include <gtk/gtk.h>
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+/* Name-Label pair */
+struct nlp
+{
+  char *name;
+  char *label;
+};
+
+struct autorecode
+{
+  PsppireDict *dict;
+  GtkWidget *change_button;
+  GtkWidget *new_name_entry;
+  GtkWidget *var_view;
+
+  /* A hash table of struct nlp's indexed by variable */
+  GHashTable *varmap;
+
+  GtkWidget *ascending;
+  GtkWidget *group;
+  GtkWidget *blank;
+};
+
+static struct nlp *
+nlp_create (const char *name, const char *label)
+{
+  struct nlp *nlp = xmalloc (sizeof *nlp);
+
+  nlp->name = g_strdup (name);
+
+  nlp->label = NULL;
+
+  if ( label != NULL && 0 != strcmp ("", label))
+    nlp->label = g_strdup (label);
+
+  return nlp;
+}
+
+static void
+nlp_destroy (gpointer data)
+{
+  struct nlp *nlp = data ;
+  if ( ! nlp )
+    return;
+
+  g_free (nlp->name);
+  g_free (nlp->label);
+  g_free (nlp);
+}
+
+static void
+on_change_clicked (GObject *obj, gpointer data)
+{
+  struct autorecode *rd = data;
+  struct variable *var = NULL;
+  struct nlp *nlp;
+  GtkTreeModel *model = GTK_TREE_MODEL (PSPPIRE_VAR_VIEW (rd->var_view)->list);
+  GtkTreeIter iter;
+  GtkTreeSelection *selection =
+    gtk_tree_view_get_selection (GTK_TREE_VIEW (rd->var_view));
+
+  GList *rows = gtk_tree_selection_get_selected_rows (selection, &model);
+
+  const gchar *dest_var_name =
+    gtk_entry_get_text (GTK_ENTRY (rd->new_name_entry));
+
+  if ( NULL == rows || rows->next != NULL)
+    goto finish;
+
+  gtk_tree_model_get_iter (model, &iter, rows->data);
+
+  gtk_tree_model_get (model, &iter, 0, &var, -1);
+
+  g_hash_table_remove (rd->varmap, var);
+
+  nlp = nlp_create (dest_var_name, NULL);
+
+  g_hash_table_insert (rd->varmap, var, nlp);
+
+  gtk_tree_model_row_changed (model, rows->data, &iter);
+
+ finish:
+  g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
+  g_list_free (rows);
+}
+
+
+static char * generate_syntax (const struct autorecode *rd);
+
+
+static void
+refresh (PsppireDialog *dialog, struct autorecode *rd)
+{
+  GtkTreeModel *target_list = gtk_tree_view_get_model (GTK_TREE_VIEW (rd->var_view));
+
+  gtk_entry_set_text (GTK_ENTRY (rd->new_name_entry), "");
+  gtk_widget_set_sensitive  (rd->new_name_entry, FALSE);
+  gtk_widget_set_sensitive  (rd->change_button, FALSE);
+
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rd->ascending), TRUE);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rd->group), FALSE);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rd->blank), FALSE);
+
+  if (rd->varmap )
+    g_hash_table_remove_all (rd->varmap);
+
+  gtk_list_store_clear (GTK_LIST_STORE (target_list));
+}
+
+
+static gboolean
+dialog_state_valid (gpointer data)
+{
+  struct autorecode *rd = data;
+
+  GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (rd->var_view));
+
+  if (g_hash_table_size (rd->varmap) != gtk_tree_model_iter_n_children (model, NULL) )
+    return FALSE;
+
+ return TRUE;
+}
+
+
+static void
+on_entry_change (struct autorecode *rd)
+{
+  gboolean valid = TRUE;
+  const char *text = gtk_entry_get_text (GTK_ENTRY (rd->new_name_entry));
+
+  if ( 0 == strcmp ("", text))
+    valid = FALSE;
+  else if (psppire_dict_lookup_var (rd->dict, text))
+    valid = FALSE;
+  else
+    {
+      GHashTableIter iter;
+      gpointer key, value;
+
+      g_hash_table_iter_init (&iter, rd->varmap);
+      while (g_hash_table_iter_next (&iter, &key, &value)) 
+       {
+         struct nlp *nlp = value;
+         
+         if ( 0 == strcmp (nlp->name, text))
+           {
+             valid = FALSE;
+             break;
+           }
+
+       }
+    }
+
+  gtk_widget_set_sensitive  (rd->change_button, valid);
+}
+
+/* Callback which gets called when a new row is selected
+   in the variable treeview.
+   It sets the name and label entry widgets to reflect the
+   currently selected row.
+ */
+static void
+on_selection_change (GtkTreeSelection *selection, gpointer data)
+{
+  struct autorecode *rd = data;
+  GtkTreeModel *model = GTK_TREE_MODEL (PSPPIRE_VAR_VIEW (rd->var_view)->list);
+  GList *rows = gtk_tree_selection_get_selected_rows (selection, &model);
+
+  if ( rows && !rows->next)
+    {
+      /* Exactly one row is selected */
+      struct nlp *nlp;
+      struct variable *var;
+      gboolean ok;
+      GtkTreeIter iter;
+
+      gtk_widget_set_sensitive  (rd->new_name_entry, TRUE);
+      gtk_widget_set_sensitive  (rd->change_button, TRUE);      
+
+
+      ok = gtk_tree_model_get_iter (model, &iter, (GtkTreePath*) rows->data);
+
+      gtk_tree_model_get (model, &iter, 0, &var, -1);
+
+      nlp = g_hash_table_lookup (rd->varmap, var);
+
+      if (nlp)
+       gtk_entry_set_text (GTK_ENTRY (rd->new_name_entry), nlp->name ? nlp->name : "");
+      else
+       gtk_entry_set_text (GTK_ENTRY (rd->new_name_entry), "");
+    }
+  else
+    {
+      gtk_entry_set_text (GTK_ENTRY (rd->new_name_entry), "");
+      gtk_widget_set_sensitive  (rd->new_name_entry, FALSE);
+      gtk_widget_set_sensitive  (rd->change_button, FALSE);
+    }
+
+  g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
+  g_list_free (rows);
+}
+
+static void
+render_new_var_name (GtkTreeViewColumn *tree_column,
+                    GtkCellRenderer *cell,
+                    GtkTreeModel *tree_model,
+                    GtkTreeIter *iter,
+                    gpointer data)
+{
+  struct nlp *nlp = NULL;
+  struct autorecode *rd = data;
+
+  struct variable *var = NULL;
+
+  gtk_tree_model_get (tree_model, iter, 
+                     0, &var,
+                     -1);
+
+  nlp = g_hash_table_lookup (rd->varmap, var);
+
+  if ( nlp )
+    g_object_set (cell, "text", nlp->name, NULL);
+  else
+    g_object_set (cell, "text", "", NULL);
+}
+
+
+
+/* Pops up the Autorecode dialog box */
+void
+autorecode_dialog (PsppireDataWindow *de)
+{
+  struct autorecode rd;
+  gint response;
+
+  GtkBuilder *xml = builder_new ("autorecode.ui");
+  PsppireVarStore *vs;
+
+  GtkWidget *dialog = get_widget_assert   (xml, "autorecode-dialog");
+  GtkWidget *source = get_widget_assert   (xml, "dict-view");
+
+  rd.var_view = get_widget_assert   (xml, "var-view");
+
+  rd.new_name_entry = get_widget_assert (xml, "entry1");
+  rd.change_button = get_widget_assert (xml, "button1");
+  rd.ascending = get_widget_assert (xml, "radiobutton1");
+  rd.group = get_widget_assert (xml, "checkbutton1");
+  rd.blank = get_widget_assert (xml, "checkbutton2");
+
+    {
+      GtkTreeSelection *sel;
+
+      GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
+
+      GtkTreeViewColumn *col = gtk_tree_view_column_new_with_attributes (_("New"),
+                                                                        renderer,
+                                                                        "text", NULL,
+                                                                        NULL);
+
+      gtk_tree_view_column_set_cell_data_func (col, renderer,
+                                              render_new_var_name,
+                                              &rd, NULL);
+
+      gtk_tree_view_append_column (GTK_TREE_VIEW (rd.var_view), col);
+
+
+      col = gtk_tree_view_get_column (GTK_TREE_VIEW (rd.var_view), 0);
+
+      g_object_set (col, "title", _("Old"), NULL);
+
+      g_object_set (rd.var_view, "headers-visible", TRUE, NULL);
+
+      rd.varmap = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, nlp_destroy);
+
+
+      sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (rd.var_view));
+
+
+      g_signal_connect (sel, "changed",
+                       G_CALLBACK (on_selection_change), &rd);
+
+      g_signal_connect (rd.change_button, "clicked",
+                       G_CALLBACK (on_change_clicked),  &rd);
+
+      g_signal_connect_swapped (rd.new_name_entry, "changed",
+                       G_CALLBACK (on_entry_change),  &rd);
+
+    }
+
+  g_object_get (de->data_editor, "var-store", &vs, NULL);
+
+  gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (de));
+
+  g_object_get (vs, "dictionary", &rd.dict, NULL);
+  g_object_set (source, "model", rd.dict, NULL);
+
+
+  g_signal_connect (dialog, "refresh", G_CALLBACK (refresh),  &rd);
+
+  psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (dialog),
+                                     dialog_state_valid, &rd);
+
+  response = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
+
+
+  switch (response)
+    {
+    case GTK_RESPONSE_OK:
+      g_free (execute_syntax_string (de, generate_syntax (&rd)));
+      break;
+    case PSPPIRE_RESPONSE_PASTE:
+      g_free (paste_syntax_to_window (generate_syntax (&rd)));
+      break;
+    default:
+      break;
+    }
+
+  g_object_unref (xml);
+}
+
+
+\f
+
+static char *
+generate_syntax (const struct autorecode *rd)
+{
+  GHashTableIter iter;
+  gpointer key, value;
+  gchar *text;
+  GString *string = g_string_new ("AUTORECODE");
+
+  g_string_append (string, "\n\tVARIABLES =");
+
+  g_hash_table_iter_init (&iter, rd->varmap);
+  while (g_hash_table_iter_next (&iter, &key, &value)) 
+  {
+    struct variable *var = key;
+    g_string_append (string, " ");
+    g_string_append (string, var_get_name (var));
+  }
+
+  g_string_append (string, " INTO");
+
+  g_hash_table_iter_init (&iter, rd->varmap);
+  while (g_hash_table_iter_next (&iter, &key, &value)) 
+  {
+    struct nlp *nlp  = value;
+    g_string_append (string, " ");
+    g_string_append (string, nlp->name);
+  }
+
+  if ( ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->ascending)))
+    g_string_append (string, "\n\t/DESCENDING");
+
+  if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->group)))
+    g_string_append (string, "\n\t/GROUP");
+
+  if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->blank)))
+    g_string_append (string, "\n\t/BLANK");
+
+  g_string_append (string, ".\n");
+
+  text = string->str;
+
+  g_string_free (string, FALSE);
+
+  return text;
+}
diff --git a/src/ui/gui/autorecode-dialog.h b/src/ui/gui/autorecode-dialog.h
new file mode 100644 (file)
index 0000000..7127b00
--- /dev/null
@@ -0,0 +1,24 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  Free Software Foundation
+
+   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/>. */
+
+#ifndef AUTORECODE_H
+#define AUTORECODE_H 1
+
+#include "psppire-data-window.h"
+
+void autorecode_dialog (PsppireDataWindow *de);
+
+#endif
diff --git a/src/ui/gui/autorecode.ui b/src/ui/gui/autorecode.ui
new file mode 100644 (file)
index 0000000..9b4a2e8
--- /dev/null
@@ -0,0 +1,291 @@
+<?xml version="1.0"?>
+<interface>
+  <!-- interface-requires psppire 0.0 -->
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="PsppireDialog" id="autorecode-dialog">
+    <property name="title" translatable="yes">Automatic Recode</property>
+    <property name="modal">True</property>
+    <child internal-child="hbox">
+      <object class="GtkHBox" id="dialog-hbox1">
+        <property name="visible">True</property>
+        <property name="spacing">2</property>
+        <child>
+          <object class="GtkVBox" id="vbox1">
+            <property name="visible">True</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkTable" id="table1">
+                <property name="visible">True</property>
+                <property name="n_rows">3</property>
+                <property name="n_columns">3</property>
+                <property name="row_spacing">5</property>
+                <child>
+                  <object class="GtkScrolledWindow" id="scrolledwindow1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hscrollbar_policy">never</property>
+                    <property name="vscrollbar_policy">automatic</property>
+                    <property name="shadow_type">in</property>
+                    <child>
+                      <object class="PsppireDictView" id="dict-view">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="has_tooltip">True</property>
+                        <property name="border_width">5</property>
+                        <property name="headers_visible">False</property>
+                        <property name="headers_clickable">False</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="bottom_attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="PsppireSelector" id="psppire-selector1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="border_width">5</property>
+                    <property name="source_widget">dict-view</property>
+                    <property name="dest_widget">var-view</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="x_options"></property>
+                    <property name="y_options">GTK_EXPAND</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkFrame" id="frame1">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">none</property>
+                    <child>
+                      <object class="GtkAlignment" id="alignment1">
+                        <property name="visible">True</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <object class="GtkScrolledWindow" id="scrolledwindow2">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="hscrollbar_policy">automatic</property>
+                            <property name="vscrollbar_policy">automatic</property>
+                            <property name="shadow_type">in</property>
+                            <child>
+                              <object class="PsppireVarView" id="var-view">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="border_width">5</property>
+                                <property name="headers_clickable">False</property>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label1">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Variable -&gt; New Name</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkFrame" id="frame2">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <child>
+                      <object class="GtkAlignment" id="alignment2">
+                        <property name="visible">True</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <object class="GtkHButtonBox" id="hbuttonbox1">
+                            <property name="visible">True</property>
+                            <child>
+                              <object class="GtkRadioButton" id="radiobutton1">
+                                <property name="label" translatable="yes">_Lowest value</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="active">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkRadioButton" id="radiobutton2">
+                                <property name="label" translatable="yes">_Highest value</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="active">True</property>
+                                <property name="draw_indicator">True</property>
+                                <property name="group">radiobutton1</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label2">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Recode starting from</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkTable" id="table2">
+                    <property name="visible">True</property>
+                    <property name="n_rows">2</property>
+                    <property name="n_columns">2</property>
+                    <property name="column_spacing">3</property>
+                    <child>
+                      <object class="GtkLabel" id="label3">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">_New Name</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">entry1</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkEntry" id="entry1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="invisible_char">&#x25CF;</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="button1">
+                        <property name="label" translatable="yes">_Add New Name</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="use_underline">True</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="top_attach">1</property>
+                        <property name="bottom_attach">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkVButtonBox" id="vbuttonbox1">
+                <property name="visible">True</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkCheckButton" id="checkbutton1">
+                    <property name="label" translatable="yes">_Use the same recoding scheme for all variables</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_underline">True</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="checkbutton2">
+                    <property name="label" translatable="yes">Treat _blank string values as missing</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_underline">True</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="PsppireVButtonBox" id="psppire-vbuttonbox1">
+            <property name="visible">True</property>
+            <property name="border_width">5</property>
+            <property name="default">PSPPIRE_BUTTON_GOTO_MASK</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
index d078391833f1af134452d73913c037c361ae2e80..7040e18eb455a71b3d6a4ba88952970f666bbea4 100644 (file)
         <property name="visible">True</property>
         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
         <child>
-          <object class="GtkTable" id="table1">
+          <object class="GtkAlignment" id="alignment1">
             <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="n_rows">3</property>
-            <property name="n_columns">3</property>
+            <property name="top_padding">5</property>
+            <property name="bottom_padding">5</property>
+            <property name="left_padding">5</property>
             <child>
-              <object class="GtkScrolledWindow" id="scrolledwindow5">
+              <object class="GtkTable" id="table1">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="hscrollbar_policy">never</property>
-                <property name="vscrollbar_policy">automatic</property>
-                <property name="shadow_type">etched-in</property>
+                <property name="n_rows">3</property>
+                <property name="n_columns">3</property>
                 <child>
-                  <object class="PsppireDictView" id="dict-view">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="headers_visible">False</property>
-                    <property name="headers_clickable">False</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkVBox" id="vbox2">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="orientation">vertical</property>
-                <child>
-                  <object class="GtkLabel" id="label1">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">_Test Variable List:</property>
-                    <property name="use_underline">True</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkScrolledWindow" id="scrolledwindow1">
+                  <object class="GtkScrolledWindow" id="scrolledwindow5">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
@@ -72,7 +37,7 @@
                     <property name="vscrollbar_policy">automatic</property>
                     <property name="shadow_type">etched-in</property>
                     <child>
-                      <object class="PsppireVarView" id="variables-treeview">
+                      <object class="PsppireDictView" id="dict-view">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                     </child>
                   </object>
                   <packing>
-                    <property name="position">1</property>
+                    <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
                   </packing>
                 </child>
-              </object>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-                <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
-              </packing>
-            </child>
-            <child>
-              <object class="PsppireSelector" id="psppire-selector1">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="border_width">5</property>
-                <property name="source_widget">dict-view</property>
-                <property name="dest_widget">variables-treeview</property>
-              </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="x_options"></property>
-                <property name="y_options">GTK_EXPAND</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFrame" id="frame1">
-                <property name="visible">True</property>
-                <property name="label_xalign">0</property>
                 <child>
-                  <object class="GtkAlignment" id="alignment1">
+                  <object class="GtkVBox" id="vbox2">
                     <property name="visible">True</property>
-                    <property name="left_padding">12</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="orientation">vertical</property>
                     <child>
-                      <object class="GtkVBox" id="vbox4">
+                      <object class="GtkLabel" id="label1">
                         <property name="visible">True</property>
-                        <property name="orientation">vertical</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">_Test Variable List:</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">variables-treeview</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkScrolledWindow" id="scrolledwindow1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="hscrollbar_policy">never</property>
+                        <property name="vscrollbar_policy">automatic</property>
+                        <property name="shadow_type">etched-in</property>
                         <child>
-                          <object class="GtkRadioButton" id="radiobutton3">
-                            <property name="label" translatable="yes">_Get from data</property>
+                          <object class="PsppireVarView" id="variables-treeview">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="use_underline">True</property>
-                            <property name="active">True</property>
-                            <property name="draw_indicator">True</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="headers_visible">False</property>
+                            <property name="headers_clickable">False</property>
                           </object>
-                          <packing>
-                            <property name="position">0</property>
-                          </packing>
                         </child>
+                      </object>
+                      <packing>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="PsppireSelector" id="psppire-selector1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="border_width">5</property>
+                    <property name="source_widget">dict-view</property>
+                    <property name="dest_widget">variables-treeview</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="x_options"></property>
+                    <property name="y_options">GTK_EXPAND</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkFrame" id="frame1">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <child>
+                      <object class="GtkAlignment" id="alignment2">
+                        <property name="visible">True</property>
+                        <property name="left_padding">12</property>
                         <child>
-                          <object class="GtkHBox" id="hbox1">
+                          <object class="GtkVBox" id="vbox4">
                             <property name="visible">True</property>
+                            <property name="orientation">vertical</property>
                             <child>
-                              <object class="GtkRadioButton" id="radiobutton4">
-                                <property name="label" translatable="yes">_Cut point:</property>
+                              <object class="GtkRadioButton" id="radiobutton3">
+                                <property name="label" translatable="yes">_Get from data</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
+                                <property name="active">True</property>
                                 <property name="draw_indicator">True</property>
-                                <property name="group">radiobutton3</property>
                               </object>
                               <packing>
                                 <property name="position">0</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkEntry" id="cutpoint-entry">
+                              <object class="GtkHBox" id="hbox1">
                                 <property name="visible">True</property>
-                                <property name="sensitive">False</property>
-                                <property name="can_focus">True</property>
-                                <property name="invisible_char">&#x2022;</property>
+                                <child>
+                                  <object class="GtkRadioButton" id="radiobutton4">
+                                    <property name="label" translatable="yes">_Cut point:</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">False</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="draw_indicator">True</property>
+                                    <property name="group">radiobutton3</property>
+                                  </object>
+                                  <packing>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkEntry" id="cutpoint-entry">
+                                    <property name="visible">True</property>
+                                    <property name="sensitive">False</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="invisible_char">&#x25CF;</property>
+                                  </object>
+                                  <packing>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
                               </object>
                               <packing>
                                 <property name="position">1</property>
                               </packing>
                             </child>
                           </object>
-                          <packing>
-                            <property name="position">1</property>
-                          </packing>
                         </child>
                       </object>
                     </child>
-                  </object>
-                </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label2">
-                    <property name="visible">True</property>
-                    <property name="label" translatable="yes">Define Dichotomy</property>
-                    <property name="use_markup">True</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">3</property>
-                <property name="y_options">GTK_FILL</property>
-                <property name="x_padding">5</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkHBox" id="hbox2">
-                <property name="visible">True</property>
-                <property name="spacing">5</property>
-                <child>
-                  <object class="GtkLabel" id="label3">
-                    <property name="visible">True</property>
-                    <property name="label" translatable="yes">Test _Proportion:</property>
-                    <property name="use_underline">True</property>
+                    <child type="label">
+                      <object class="GtkLabel" id="label2">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Define Dichotomy</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                    </child>
                   </object>
                   <packing>
-                    <property name="position">0</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">3</property>
+                    <property name="y_options">GTK_FILL</property>
+                    <property name="x_padding">5</property>
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkEntry" id="proportion-entry">
+                  <object class="GtkHBox" id="hbox2">
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="invisible_char">&#x2022;</property>
+                    <property name="spacing">5</property>
+                    <child>
+                      <object class="GtkLabel" id="label3">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Test _Proportion:</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">proportion-entry</property>
+                      </object>
+                      <packing>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkEntry" id="proportion-entry">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="invisible_char">&#x25CF;</property>
+                      </object>
+                      <packing>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
                   </object>
                   <packing>
-                    <property name="position">1</property>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="y_options"></property>
                   </packing>
                 </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
               </object>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <placeholder/>
-            </child>
-            <child>
-              <placeholder/>
-            </child>
-            <child>
-              <placeholder/>
             </child>
           </object>
           <packing>
index 5bcc08d56aea99b13515d33979cf841a2abb4ea3..8544485b8a6268a06fbeeea2db02ba187f9a6c1f 100644 (file)
         <property name="visible">True</property>
         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
         <child>
-          <object class="GtkTable" id="table1">
+          <object class="GtkAlignment" id="alignment1">
             <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="n_rows">2</property>
-            <property name="n_columns">3</property>
+            <property name="top_padding">5</property>
+            <property name="bottom_padding">5</property>
+            <property name="left_padding">5</property>
             <child>
-              <object class="GtkScrolledWindow" id="scrolledwindow5">
+              <object class="GtkTable" id="table1">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="hscrollbar_policy">never</property>
-                <property name="vscrollbar_policy">automatic</property>
-                <property name="shadow_type">etched-in</property>
+                <property name="n_rows">2</property>
+                <property name="n_columns">3</property>
                 <child>
-                  <object class="PsppireDictView" id="dict-view">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="headers_visible">False</property>
-                    <property name="headers_clickable">False</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkVBox" id="vbox2">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="orientation">vertical</property>
-                <child>
-                  <object class="GtkLabel" id="label1">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">_Test Variable List:</property>
-                    <property name="use_underline">True</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkScrolledWindow" id="scrolledwindow1">
+                  <object class="GtkScrolledWindow" id="scrolledwindow5">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
@@ -72,7 +37,7 @@
                     <property name="vscrollbar_policy">automatic</property>
                     <property name="shadow_type">etched-in</property>
                     <child>
-                      <object class="PsppireVarView" id="variables-treeview">
+                      <object class="PsppireDictView" id="dict-view">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                       </object>
                     </child>
                   </object>
+                </child>
+                <child>
+                  <object class="PsppireSelector" id="psppire-selector1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="border_width">5</property>
+                    <property name="source_widget">dict-view</property>
+                    <property name="dest_widget">variables-treeview</property>
+                  </object>
                   <packing>
-                    <property name="position">1</property>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="x_options"></property>
+                    <property name="y_options">GTK_EXPAND</property>
                   </packing>
                 </child>
-              </object>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-                <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
-              </packing>
-            </child>
-            <child>
-              <object class="PsppireSelector" id="psppire-selector1">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="border_width">5</property>
-                <property name="source_widget">dict-view</property>
-                <property name="dest_widget">variables-treeview</property>
-              </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="x_options"></property>
-                <property name="y_options">GTK_EXPAND</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFrame" id="frame1">
-                <property name="visible">True</property>
-                <property name="label_xalign">0</property>
                 <child>
-                  <object class="GtkAlignment" id="alignment1">
+                  <object class="GtkFrame" id="frame1">
                     <property name="visible">True</property>
-                    <property name="left_padding">12</property>
+                    <property name="label_xalign">0</property>
                     <child>
-                      <object class="GtkVBox" id="vbox4">
+                      <object class="GtkAlignment" id="alignment2">
                         <property name="visible">True</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkRadioButton" id="radiobutton3">
-                            <property name="label" translatable="yes">_Get from data</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="use_underline">True</property>
-                            <property name="active">True</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkRadioButton" id="radiobutton4">
-                            <property name="label" translatable="yes">Use _specified range</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="use_underline">True</property>
-                            <property name="draw_indicator">True</property>
-                            <property name="group">radiobutton3</property>
-                          </object>
-                          <packing>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
+                        <property name="bottom_padding">5</property>
+                        <property name="left_padding">5</property>
+                        <property name="right_padding">5</property>
                         <child>
-                          <object class="GtkTable" id="range-table">
+                          <object class="GtkVBox" id="vbox4">
                             <property name="visible">True</property>
-                            <property name="sensitive">False</property>
-                            <property name="n_rows">2</property>
-                            <property name="n_columns">2</property>
-                            <property name="column_spacing">5</property>
+                            <property name="orientation">vertical</property>
                             <child>
-                              <object class="GtkLabel" id="label4">
+                              <object class="GtkRadioButton" id="radiobutton3">
+                                <property name="label" translatable="yes">_Get from data</property>
                                 <property name="visible">True</property>
-                                <property name="label" translatable="yes">_Lower:</property>
-                                <property name="use_markup">True</property>
-                                <property name="use_underline">True</property>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="label5">
-                                <property name="visible">True</property>
-                                <property name="label" translatable="yes">_Upper:</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
+                                <property name="active">True</property>
+                                <property name="draw_indicator">True</property>
                               </object>
                               <packing>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">0</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkEntry" id="entry1">
+                              <object class="GtkRadioButton" id="radiobutton4">
+                                <property name="label" translatable="yes">Use _specified range</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
-                                <property name="invisible_char">&#x2022;</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                                <property name="group">radiobutton3</property>
                               </object>
                               <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">1</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkEntry" id="entry2">
+                              <object class="GtkTable" id="range-table">
                                 <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="invisible_char">&#x2022;</property>
+                                <property name="sensitive">False</property>
+                                <property name="n_rows">2</property>
+                                <property name="n_columns">2</property>
+                                <property name="column_spacing">5</property>
+                                <child>
+                                  <object class="GtkLabel" id="label4">
+                                    <property name="visible">True</property>
+                                    <property name="label" translatable="yes">_Lower:</property>
+                                    <property name="use_markup">True</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">entry1</property>
+                                  </object>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel" id="label5">
+                                    <property name="visible">True</property>
+                                    <property name="label" translatable="yes">_Upper:</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">entry2</property>
+                                  </object>
+                                  <packing>
+                                    <property name="top_attach">1</property>
+                                    <property name="bottom_attach">2</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkEntry" id="entry1">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="invisible_char">&#x25CF;</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">1</property>
+                                    <property name="right_attach">2</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkEntry" id="entry2">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="invisible_char">&#x25CF;</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">1</property>
+                                    <property name="right_attach">2</property>
+                                    <property name="top_attach">1</property>
+                                    <property name="bottom_attach">2</property>
+                                  </packing>
+                                </child>
                               </object>
                               <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">2</property>
                               </packing>
                             </child>
                           </object>
-                          <packing>
-                            <property name="position">2</property>
-                          </packing>
                         </child>
                       </object>
                     </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label2">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Expected Range:</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                    </child>
                   </object>
+                  <packing>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="y_options"></property>
+                    <property name="x_padding">5</property>
+                  </packing>
                 </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label2">
-                    <property name="visible">True</property>
-                    <property name="label" translatable="yes">Expected Range:</property>
-                    <property name="use_markup">True</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-                <property name="y_options">GTK_FILL</property>
-                <property name="x_padding">5</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFrame" id="frame2">
-                <property name="visible">True</property>
-                <property name="label_xalign">0</property>
                 <child>
-                  <object class="GtkAlignment" id="alignment2">
+                  <object class="GtkFrame" id="frame2">
                     <property name="visible">True</property>
-                    <property name="left_padding">12</property>
+                    <property name="label_xalign">0</property>
                     <child>
-                      <object class="GtkVBox" id="vbox3">
+                      <object class="GtkAlignment" id="alignment3">
                         <property name="visible">True</property>
-                        <property name="orientation">vertical</property>
+                        <property name="left_padding">5</property>
+                        <property name="right_padding">5</property>
                         <child>
-                          <object class="GtkRadioButton" id="radiobutton1">
-                            <property name="label" translatable="yes">All categor_ies equal</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="use_underline">True</property>
-                            <property name="active">True</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkHBox" id="hbox1">
+                          <object class="GtkVBox" id="vbox3">
                             <property name="visible">True</property>
+                            <property name="orientation">vertical</property>
                             <child>
-                              <object class="GtkRadioButton" id="radiobutton2">
-                                <property name="label" translatable="yes">_Values</property>
+                              <object class="GtkRadioButton" id="radiobutton1">
+                                <property name="label" translatable="yes">All categor_ies equal</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
                                 <property name="use_underline">True</property>
+                                <property name="active">True</property>
                                 <property name="draw_indicator">True</property>
-                                <property name="group">radiobutton1</property>
                               </object>
                               <packing>
                                 <property name="position">0</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkEntry" id="expected-value-entry">
+                              <object class="GtkHBox" id="hbox1">
                                 <property name="visible">True</property>
-                                <property name="sensitive">False</property>
-                                <property name="can_focus">True</property>
-                                <property name="invisible_char">&#x2022;</property>
+                                <child>
+                                  <object class="GtkRadioButton" id="radiobutton2">
+                                    <property name="label" translatable="yes">_Values</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">False</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="draw_indicator">True</property>
+                                    <property name="group">radiobutton1</property>
+                                  </object>
+                                  <packing>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkEntry" id="expected-value-entry">
+                                    <property name="visible">True</property>
+                                    <property name="sensitive">False</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="invisible_char">&#x25CF;</property>
+                                  </object>
+                                  <packing>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
                               </object>
                               <packing>
                                 <property name="position">1</property>
                               </packing>
                             </child>
+                            <child>
+                              <object class="PsppireAcr" id="psppire-acr1">
+                                <property name="visible">True</property>
+                                <property name="border_width">5</property>
+                                <child>
+                                  <placeholder/>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
                           </object>
-                          <packing>
-                            <property name="position">1</property>
-                          </packing>
                         </child>
+                      </object>
+                    </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label3">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Expected Values:</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="y_options"></property>
+                    <property name="x_padding">5</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkFrame" id="frame3">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">none</property>
+                    <child>
+                      <object class="GtkAlignment" id="alignment4">
+                        <property name="visible">True</property>
+                        <property name="left_padding">12</property>
                         <child>
-                          <object class="PsppireAcr" id="psppire-acr1">
+                          <object class="GtkScrolledWindow" id="scrolledwindow1">
                             <property name="visible">True</property>
-                            <property name="border_width">5</property>
+                            <property name="can_focus">True</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="hscrollbar_policy">never</property>
+                            <property name="vscrollbar_policy">automatic</property>
+                            <property name="shadow_type">etched-in</property>
+                            <child>
+                              <object class="PsppireVarView" id="variables-treeview">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="headers_visible">False</property>
+                                <property name="headers_clickable">False</property>
+                              </object>
+                            </child>
                           </object>
-                          <packing>
-                            <property name="position">2</property>
-                          </packing>
                         </child>
                       </object>
                     </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label1">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Test _Variables</property>
+                        <property name="use_markup">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">variables-treeview</property>
+                      </object>
+                    </child>
                   </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                  </packing>
                 </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label3">
-                    <property name="visible">True</property>
-                    <property name="label" translatable="yes">Expected Values:</property>
-                    <property name="use_markup">True</property>
-                  </object>
+                <child>
+                  <placeholder/>
                 </child>
               </object>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-                <property name="y_options">GTK_FILL</property>
-                <property name="x_padding">5</property>
-              </packing>
-            </child>
-            <child>
-              <placeholder/>
             </child>
           </object>
           <packing>
index 1fad344060dc6b4539a641170a1029519068e401..d9fcdca3d86243e8a67d0c3ae324550dd03a5fca 100644 (file)
         <property name="visible">True</property>
         <property name="spacing">2</property>
         <child>
-          <object class="GtkVBox" id="vbox1">
+          <object class="GtkAlignment" id="alignment1">
             <property name="visible">True</property>
-            <property name="orientation">vertical</property>
-            <property name="spacing">5</property>
+            <property name="top_padding">5</property>
+            <property name="bottom_padding">5</property>
+            <property name="left_padding">5</property>
             <child>
-              <object class="GtkHBox" id="hbox1">
+              <object class="GtkVBox" id="vbox1">
                 <property name="visible">True</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">5</property>
                 <child>
-                  <object class="GtkScrolledWindow" id="scrolledwindow1">
+                  <object class="GtkHBox" id="hbox1">
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="hscrollbar_policy">automatic</property>
-                    <property name="vscrollbar_policy">automatic</property>
-                    <property name="shadow_type">in</property>
                     <child>
-                      <object class="PsppireDictView" id="dict-view">
+                      <object class="GtkScrolledWindow" id="scrolledwindow1">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="border_width">5</property>
-                        <property name="headers_visible">False</property>
-                        <property name="headers_clickable">False</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkVBox" id="vbox2">
-                    <property name="visible">True</property>
-                    <property name="orientation">vertical</property>
-                    <child>
-                      <object class="PsppireSelector" id="psppire-selector1">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="border_width">5</property>
-                        <property name="source_widget">dict-view</property>
-                        <property name="dest_widget">psppire-var-view1</property>
+                        <property name="hscrollbar_policy">never</property>
+                        <property name="vscrollbar_policy">automatic</property>
+                        <property name="shadow_type">in</property>
+                        <child>
+                          <object class="PsppireDictView" id="dict-view">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="border_width">5</property>
+                            <property name="headers_visible">False</property>
+                            <property name="headers_clickable">False</property>
+                          </object>
+                        </child>
                       </object>
                       <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
                         <property name="position">0</property>
                       </packing>
                     </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="padding">5</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkScrolledWindow" id="scrolledwindow2">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="hscrollbar_policy">automatic</property>
-                    <property name="vscrollbar_policy">automatic</property>
-                    <property name="shadow_type">in</property>
-                    <child>
-                      <object class="PsppireVarView" id="psppire-var-view1">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="border_width">5</property>
-                        <property name="headers_visible">False</property>
-                        <property name="headers_clickable">False</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFrame" id="frame2">
-                <property name="label_xalign">0</property>
-                <child>
-                  <object class="GtkAlignment" id="alignment2">
-                    <property name="visible">True</property>
-                    <property name="left_padding">12</property>
                     <child>
-                      <object class="GtkHButtonBox" id="hbuttonbox2">
+                      <object class="GtkVBox" id="vbox2">
                         <property name="visible">True</property>
-                        <property name="layout_style">start</property>
+                        <property name="orientation">vertical</property>
+                        <property name="homogeneous">True</property>
                         <child>
-                          <object class="GtkCheckButton" id="button-pearson">
-                            <property name="label" translatable="yes">Pearso_n</property>
+                          <object class="PsppireSelector" id="psppire-selector1">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="use_underline">True</property>
-                            <property name="draw_indicator">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="border_width">5</property>
+                            <property name="source_widget">dict-view</property>
+                            <property name="dest_widget">psppire-var-view1</property>
                           </object>
                           <packing>
                             <property name="expand">False</property>
                             <property name="position">0</property>
                           </packing>
                         </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="padding">5</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkScrolledWindow" id="scrolledwindow2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="hscrollbar_policy">never</property>
+                        <property name="vscrollbar_policy">automatic</property>
+                        <property name="shadow_type">in</property>
                         <child>
-                          <object class="GtkCheckButton" id="button-kendall">
-                            <property name="label" translatable="yes">_Kendall's tau-b</property>
+                          <object class="PsppireVarView" id="psppire-var-view1">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="use_underline">True</property>
-                            <property name="draw_indicator">True</property>
+                            <property name="border_width">5</property>
+                            <property name="headers_visible">False</property>
+                            <property name="headers_clickable">False</property>
                           </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
                         </child>
+                      </object>
+                      <packing>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkFrame" id="frame2">
+                    <property name="label_xalign">0</property>
+                    <child>
+                      <object class="GtkAlignment" id="alignment2">
+                        <property name="visible">True</property>
+                        <property name="left_padding">12</property>
                         <child>
-                          <object class="GtkCheckButton" id="button-spearman">
-                            <property name="label" translatable="yes">_Spearman</property>
+                          <object class="GtkHButtonBox" id="hbuttonbox2">
                             <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="use_underline">True</property>
-                            <property name="draw_indicator">True</property>
+                            <property name="layout_style">start</property>
+                            <child>
+                              <object class="GtkCheckButton" id="button-pearson">
+                                <property name="label" translatable="yes">Pearso_n</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="button-kendall">
+                                <property name="label" translatable="yes">_Kendall's tau-b</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="button-spearman">
+                                <property name="label" translatable="yes">_Spearman</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
                           </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">2</property>
-                          </packing>
                         </child>
                       </object>
                     </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label2">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Correlation Coefficients</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                    </child>
                   </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">1</property>
+                  </packing>
                 </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label2">
-                    <property name="visible">True</property>
-                    <property name="label" translatable="yes">Correlation Coefficients</property>
-                    <property name="use_markup">True</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFrame" id="frame1">
-                <property name="visible">True</property>
-                <property name="label_xalign">0</property>
                 <child>
-                  <object class="GtkAlignment" id="alignment1">
+                  <object class="GtkFrame" id="frame1">
                     <property name="visible">True</property>
-                    <property name="left_padding">12</property>
+                    <property name="label_xalign">0</property>
                     <child>
-                      <object class="GtkHButtonBox" id="hbuttonbox1">
+                      <object class="GtkAlignment" id="alignment3">
                         <property name="visible">True</property>
-                        <property name="layout_style">start</property>
+                        <property name="left_padding">12</property>
                         <child>
-                          <object class="GtkRadioButton" id="button-two-tailed">
-                            <property name="label" translatable="yes">_Two-tailed</property>
+                          <object class="GtkHButtonBox" id="hbuttonbox1">
                             <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="use_underline">True</property>
-                            <property name="active">True</property>
-                            <property name="draw_indicator">True</property>
+                            <property name="layout_style">start</property>
+                            <child>
+                              <object class="GtkRadioButton" id="button-two-tailed">
+                                <property name="label" translatable="yes">_Two-tailed</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="active">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkRadioButton" id="button-one-tailed">
+                                <property name="label" translatable="yes">One-tai_led</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                                <property name="group">button-two-tailed</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
                           </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkRadioButton" id="button-one-tailed">
-                            <property name="label" translatable="yes">One-tai_led</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="use_underline">True</property>
-                            <property name="active">True</property>
-                            <property name="draw_indicator">True</property>
-                            <property name="group">button-two-tailed</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
                         </child>
                       </object>
                     </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label1">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Test of Significance</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                    </child>
                   </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">2</property>
+                  </packing>
                 </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label1">
+                <child>
+                  <object class="GtkCheckButton" id="button-flag-significants">
+                    <property name="label" translatable="yes">_Flag significant correlations</property>
                     <property name="visible">True</property>
-                    <property name="label" translatable="yes">Test of Significance</property>
-                    <property name="use_markup">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_underline">True</property>
+                    <property name="draw_indicator">True</property>
                   </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">3</property>
+                  </packing>
                 </child>
               </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkCheckButton" id="button-flag-significants">
-                <property name="label" translatable="yes">_Flag significant correlations</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">False</property>
-                <property name="use_underline">True</property>
-                <property name="draw_indicator">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="position">3</property>
-              </packing>
             </child>
           </object>
           <packing>
-            <property name="padding">2</property>
             <property name="position">0</property>
           </packing>
         </child>
diff --git a/src/ui/gui/count-dialog.c b/src/ui/gui/count-dialog.c
new file mode 100644 (file)
index 0000000..39a99db
--- /dev/null
@@ -0,0 +1,293 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  Free Software Foundation
+
+   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 "count-dialog.h"
+
+#include <gtk/gtk.h>
+#include "helper.h"
+#include "psppire-dialog.h"
+#include "psppire-selector.h"
+#include "psppire-val-chooser.h"
+#include "psppire-var-view.h"
+#include "psppire-acr.h"
+#include "dialog-common.h"
+
+#include <ui/syntax-gen.h>
+#include "executor.h"
+
+struct cnt_dialog
+{
+  PsppireDict *dict;
+
+  GtkWidget *dialog;
+
+  GtkListStore *value_list;
+  GtkWidget *chooser;
+
+  GtkWidget *target;
+  GtkWidget *label;
+  GtkWidget *variable_treeview;
+};
+
+/* Callback which gets called when a new row is selected
+   in the acr's variable treeview.
+   We use if to set the togglebuttons and entries to correspond to the
+   selected row.
+*/
+static void
+on_acr_selection_change (GtkTreeSelection *selection, gpointer data)
+{
+  GtkTreeIter iter;
+  struct old_value *ov = NULL;
+  GtkTreeModel *model = NULL;
+  struct cnt_dialog *cnt = data;
+  GValue ov_value = {0};
+
+  if ( ! gtk_tree_selection_get_selected (selection, &model, &iter) )
+    return;
+
+  gtk_tree_model_get_value (GTK_TREE_MODEL (model), &iter,
+                           0, &ov_value);
+
+  ov = g_value_get_boxed (&ov_value);
+  psppire_val_chooser_set_status (PSPPIRE_VAL_CHOOSER (cnt->chooser), ov);
+}
+
+
+
+static char * generate_syntax (const struct cnt_dialog *cnt);
+
+static void values_dialog (struct cnt_dialog *cd);
+
+static void
+refresh (PsppireDialog *dialog, struct cnt_dialog *cnt)
+{
+  GtkTreeModel *vars =
+    gtk_tree_view_get_model (GTK_TREE_VIEW (cnt->variable_treeview));
+
+  gtk_list_store_clear (GTK_LIST_STORE (vars));
+
+  gtk_entry_set_text (GTK_ENTRY (cnt->target), "");
+  gtk_entry_set_text (GTK_ENTRY (cnt->label), "");
+  gtk_list_store_clear (GTK_LIST_STORE (cnt->value_list));
+}
+
+static gboolean
+dialog_state_valid (gpointer data)
+{
+  GtkTreeIter iter;
+  struct cnt_dialog *cnt = data;
+
+  if (! cnt->value_list)
+    return FALSE;
+
+  if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (cnt->value_list),        &iter) )
+    return FALSE;
+
+  if (!gtk_tree_model_get_iter_first (gtk_tree_view_get_model (GTK_TREE_VIEW (cnt->variable_treeview)), &iter))
+    return FALSE;
+
+  if (0 == strcmp ("", gtk_entry_get_text (GTK_ENTRY (cnt->target))))
+    return FALSE;
+
+  return TRUE;
+}
+
+void count_dialog (PsppireDataWindow *de)
+{
+  gint response;
+  PsppireVarStore *vs = NULL;
+  struct cnt_dialog cnt;
+
+  GtkBuilder *builder = builder_new ("count.ui");
+
+  GtkWidget *selector = get_widget_assert (builder, "count-selector1");
+
+  GtkWidget *dict_view = get_widget_assert (builder, "dict-view");
+  GtkWidget *button = get_widget_assert (builder, "button1");
+
+  cnt.target = get_widget_assert (builder, "entry1");
+  cnt.label = get_widget_assert (builder, "entry2");
+  cnt.variable_treeview = get_widget_assert (builder, "treeview2");
+
+  g_signal_connect_swapped (button, "clicked", G_CALLBACK (values_dialog), &cnt);
+
+  cnt.value_list = gtk_list_store_new (1,old_value_get_type ());
+
+  cnt.dialog =  get_widget_assert (builder, "count-dialog");
+
+  g_signal_connect (cnt.dialog, "refresh", G_CALLBACK (refresh),  &cnt);
+
+
+  g_object_get (de->data_editor, "var-store", &vs, NULL);
+
+  g_object_get (vs, "dictionary", &cnt.dict, NULL);
+
+  gtk_window_set_transient_for (GTK_WINDOW (cnt.dialog), GTK_WINDOW (de));
+
+  g_object_set (dict_view, "model", cnt.dict, NULL);
+
+  psppire_selector_set_allow (PSPPIRE_SELECTOR (selector),  numeric_only);
+
+  psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (cnt.dialog),
+                                     dialog_state_valid, &cnt);
+
+  response = psppire_dialog_run (PSPPIRE_DIALOG (cnt.dialog));
+
+  switch (response)
+    {
+    case GTK_RESPONSE_OK:
+      g_free (execute_syntax_string (de, generate_syntax (&cnt)));
+      break;
+    case PSPPIRE_RESPONSE_PASTE:
+      g_free (paste_syntax_to_window (generate_syntax (&cnt)));
+      break;
+    default:
+      break;
+    }
+
+
+  g_object_unref (builder);
+}
+
+/* A function to set a value in a column in the ACR */
+static gboolean
+set_value (gint col, GValue  *val, gpointer data)
+{
+  struct cnt_dialog *cnt = data;
+  PsppireValChooser *vc = PSPPIRE_VAL_CHOOSER (cnt->chooser);
+  struct old_value ov;
+       
+  g_assert (col == 0);
+
+  psppire_val_chooser_get_status (vc, &ov);
+
+  g_value_init (val, old_value_get_type ());
+  g_value_set_boxed (val, &ov);
+
+  return TRUE;
+}
+
+
+static void
+values_dialog (struct cnt_dialog *cd)
+{
+  gint response;
+  GtkListStore *local_store = clone_list_store (cd->value_list);
+  GtkBuilder *builder = builder_new ("count.ui");
+
+  GtkWidget *dialog = get_widget_assert (builder, "values-dialog");
+
+  GtkWidget *acr = get_widget_assert (builder, "acr");
+  cd->chooser = get_widget_assert (builder, "value-chooser");
+
+  psppire_acr_set_enabled (PSPPIRE_ACR (acr), TRUE);
+
+  psppire_acr_set_model (PSPPIRE_ACR (acr), local_store);
+  psppire_acr_set_get_value_func (PSPPIRE_ACR (acr), set_value, cd);
+
+  {
+    GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (PSPPIRE_ACR(acr)->tv));
+    g_signal_connect (sel, "changed",
+                   G_CALLBACK (on_acr_selection_change), cd);
+  }
+
+  response = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
+
+  if ( response == PSPPIRE_RESPONSE_CONTINUE )
+    {
+      g_object_unref (cd->value_list);
+      cd->value_list = local_store;
+    }
+  else
+    {
+      g_object_unref (local_store);
+    }
+
+  psppire_dialog_notify_change (PSPPIRE_DIALOG (cd->dialog));
+
+  g_object_unref (builder);
+}
+
+
+
+static char *
+generate_syntax (const struct cnt_dialog *cnt)
+{
+  gchar *text = NULL;
+  const gchar *s = NULL;
+  gboolean ok;
+  GtkTreeIter iter;
+  GString *str = g_string_sized_new (100);
+
+  g_string_append (str, "\nCOUNT ");
+
+  g_string_append (str, gtk_entry_get_text (GTK_ENTRY (cnt->target)));
+
+  g_string_append (str, " =");
+
+  psppire_var_view_append_names (PSPPIRE_VAR_VIEW (cnt->variable_treeview), 0, str);
+
+  g_string_append (str, "(");
+  for (ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (cnt->value_list),
+                                          &iter);
+       ok;
+       ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (cnt->value_list), &iter))
+    {
+      GValue a_value = {0};
+      struct old_value *ov;
+
+      gtk_tree_model_get_value (GTK_TREE_MODEL (cnt->value_list), &iter,
+                               0, &a_value);
+
+      ov = g_value_get_boxed (&a_value);
+
+      g_string_append (str, " ");
+      old_value_append_syntax (str, ov);
+    }
+  g_string_append (str, ").");
+
+
+  s = gtk_entry_get_text (GTK_ENTRY (cnt->label));
+  if (0 != strcmp (s, ""))
+  {
+    struct string ds;
+    ds_init_empty (&ds);
+    g_string_append (str, "\nVARIABLE LABELS ");
+
+    g_string_append (str, gtk_entry_get_text (GTK_ENTRY (cnt->target)));
+
+    g_string_append (str, " ");
+
+    syntax_gen_string (&ds, ss_cstr (s));
+
+    g_string_append (str, ds_cstr (&ds));
+
+    g_string_append (str, ".");
+    ds_destroy (&ds);
+  }
+
+  g_string_append (str, "\nEXECUTE.\n");
+
+  text = str->str;
+
+  g_string_free (str, FALSE);
+
+  return text;
+}
diff --git a/src/ui/gui/count-dialog.h b/src/ui/gui/count-dialog.h
new file mode 100644 (file)
index 0000000..d97765d
--- /dev/null
@@ -0,0 +1,24 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  Free Software Foundation
+
+   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/>. */
+
+#ifndef __COUNT_DIALOG_H
+#define __COUNT_DIALOG_H
+
+#include "psppire-data-window.h"
+
+void count_dialog (PsppireDataWindow * data);
+
+#endif
diff --git a/src/ui/gui/count.ui b/src/ui/gui/count.ui
new file mode 100644 (file)
index 0000000..13ab131
--- /dev/null
@@ -0,0 +1,304 @@
+<?xml version="1.0"?>
+<interface>
+  <!-- interface-requires psppire 0.0 -->
+  <!-- interface-requires gtk+ 2.12 -->
+  <!-- interface-naming-policy toplevel-contextual -->
+  <object class="PsppireDialog" id="count-dialog">
+    <property name="title" translatable="yes">Count Occurrences of Values within Cases</property>
+    <property name="modal">True</property>
+    <child internal-child="hbox">
+      <object class="GtkHBox" id="dialog-hbox5">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkAlignment" id="alignment1">
+            <property name="visible">True</property>
+            <property name="top_padding">5</property>
+            <property name="bottom_padding">5</property>
+            <property name="left_padding">5</property>
+            <property name="right_padding">5</property>
+            <child>
+              <object class="GtkTable" id="table1">
+                <property name="visible">True</property>
+                <property name="n_rows">4</property>
+                <property name="n_columns">3</property>
+                <child>
+                  <object class="GtkScrolledWindow" id="scrolledwindow1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hscrollbar_policy">never</property>
+                    <property name="vscrollbar_policy">automatic</property>
+                    <property name="shadow_type">etched-in</property>
+                    <child>
+                      <object class="PsppireDictView" id="dict-view">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="border_width">5</property>
+                        <property name="headers_visible">False</property>
+                        <property name="headers_clickable">False</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">4</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="PsppireSelector" id="count-selector1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="no_show_all">True</property>
+                    <property name="border_width">5</property>
+                    <property name="source_widget">dict-view</property>
+                    <property name="dest_widget">treeview2</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="x_options"></property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkFrame" id="frame1">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">none</property>
+                    <child>
+                      <object class="GtkAlignment" id="alignment3">
+                        <property name="visible">True</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <object class="GtkScrolledWindow" id="scrolledwindow2">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="hscrollbar_policy">never</property>
+                            <property name="vscrollbar_policy">automatic</property>
+                            <property name="shadow_type">etched-in</property>
+                            <child>
+                              <object class="PsppireVarView" id="treeview2">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="headers_visible">False</property>
+                                <property name="headers_clickable">False</property>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label1">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Numeric _Variables:</property>
+                        <property name="use_markup">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">treeview2</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkFrame" id="frame2">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">none</property>
+                    <child>
+                      <object class="GtkAlignment" id="alignment2">
+                        <property name="visible">True</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <object class="GtkEntry" id="entry1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">&#x2022;</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label2">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">_Target Variable:</property>
+                        <property name="use_markup">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">entry1</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="y_options">GTK_SHRINK</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkFrame" id="frame3">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">none</property>
+                    <child>
+                      <object class="GtkAlignment" id="alignment4">
+                        <property name="visible">True</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <object class="GtkEntry" id="entry2">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">&#x2022;</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label3">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Target _Label:</property>
+                        <property name="use_markup">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">entry2</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="y_options">GTK_SHRINK</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="button1">
+                    <property name="label" translatable="yes">_Define Values...</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="use_underline">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                    <property name="x_options">GTK_EXPAND</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="PsppireHButtonBox" id="psppire-hbuttonbox1">
+            <property name="visible">True</property>
+            <property name="border_width">5</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+  <object class="PsppireDialog" id="values-dialog">
+    <property name="title" translatable="yes">Count Values within Cases: Values to Count</property>
+    <property name="modal">True</property>
+    <property name="orientation">Vertical</property>
+    <child internal-child="hbox">
+      <object class="GtkVBox" id="dialog-hbox6">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child>
+          <object class="GtkHBox" id="hbox1">
+            <property name="visible">True</property>
+            <child>
+              <object class="PsppireValChooser" id="value-chooser">
+                <property name="visible">True</property>
+                <property name="show-else">False</property>
+               <property name="label" translatable="yes">Value</property>
+              </object>
+              <packing>
+                <property name="position">0</property>
+                <property name="padding">5</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkFrame" id="frame-acr">
+                <property name="visible">True</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">etched-in</property>
+                <child>
+                  <object class="GtkAlignment" id="alignment-acr">
+                    <property name="visible">True</property>
+                    <property name="left_padding">12</property>
+                    <child>
+                      <object class="PsppireAcr" id="acr">
+                        <property name="visible">True</property>
+                        <property name="border_width">5</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label-v2c">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Values _to Count:</property>
+                    <property name="use_markup">True</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">acr</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="PsppireHButtonBox" id="psppire-hbuttonbox2">
+            <property name="visible">True</property>
+            <property name="border_width">5</property>
+            <property name="buttons">PSPPIRE_BUTTON_CONTINUE_MASK | PSPPIRE_BUTTON_CANCEL_MASK | PSPPIRE_BUTTON_HELP_MASK</property>
+            <property name="default">PSPPIRE_BUTTON_CONTINUE_MASK</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
index 7f0c0284177e96ec5a6ebb62a681ec58d1717743..19d76894b7a4ec56c26cdc830dc226acbfb3e19d 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <interface>
-  <!-- interface-requires gtk+ 2.12 -->
   <requires lib="psppire" version="2054.22072"/>
+  <!-- interface-requires gtk+ 2.12 -->
   <!-- interface-naming-policy toplevel-contextual -->
   <object class="PsppireDialog" id="crosstabs-dialog">
     <property name="title" translatable="yes">Crosstabs</property>
         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
         <property name="spacing">2</property>
         <child>
-          <object class="GtkTable" id="table1">
+          <object class="GtkAlignment" id="alignment1">
             <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="n_rows">3</property>
-            <property name="n_columns">3</property>
+            <property name="top_padding">5</property>
+            <property name="left_padding">5</property>
             <child>
-              <object class="GtkFrame" id="frame1">
+              <object class="GtkTable" id="table1">
                 <property name="visible">True</property>
-                <property name="label_xalign">0</property>
-                <property name="shadow_type">none</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="n_rows">3</property>
+                <property name="n_columns">3</property>
                 <child>
-                  <object class="GtkAlignment" id="alignment4">
+                  <object class="GtkFrame" id="frame1">
                     <property name="visible">True</property>
-                    <property name="left_padding">12</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">none</property>
                     <child>
-                      <object class="GtkScrolledWindow" id="scrolledwindow2">
+                      <object class="GtkAlignment" id="alignment4">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="hscrollbar_policy">never</property>
-                        <property name="vscrollbar_policy">automatic</property>
-                        <property name="shadow_type">etched-in</property>
+                        <property name="left_padding">12</property>
                         <child>
-                          <object class="PsppireVarView" id="rows">
+                          <object class="GtkScrolledWindow" id="scrolledwindow2">
                             <property name="visible">True</property>
-                            <property name="headers_visible">False</property>
+                            <property name="can_focus">True</property>
+                            <property name="hscrollbar_policy">never</property>
+                            <property name="vscrollbar_policy">automatic</property>
+                            <property name="shadow_type">etched-in</property>
+                            <child>
+                              <object class="PsppireVarView" id="rows">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="headers_visible">False</property>
+                                <property name="headers_clickable">False</property>
+                              </object>
+                            </child>
                           </object>
                         </child>
                       </object>
                     </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label1">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="label" translatable="yes">_Rows</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">rows</property>
+                      </object>
+                    </child>
                   </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                  </packing>
                 </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label1">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label" translatable="yes">Rows</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFrame" id="frame2">
-                <property name="visible">True</property>
-                <property name="label_xalign">0</property>
-                <property name="shadow_type">none</property>
                 <child>
-                  <object class="GtkAlignment" id="alignment5">
+                  <object class="GtkFrame" id="frame2">
                     <property name="visible">True</property>
-                    <property name="left_padding">12</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">none</property>
                     <child>
-                      <object class="GtkScrolledWindow" id="scrolledwindow3">
+                      <object class="GtkAlignment" id="alignment5">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="hscrollbar_policy">never</property>
-                        <property name="vscrollbar_policy">automatic</property>
-                        <property name="shadow_type">etched-in</property>
+                        <property name="left_padding">12</property>
                         <child>
-                          <object class="PsppireVarView" id="cols">
+                          <object class="GtkScrolledWindow" id="scrolledwindow3">
                             <property name="visible">True</property>
-                            <property name="headers_visible">False</property>
+                            <property name="can_focus">True</property>
+                            <property name="hscrollbar_policy">never</property>
+                            <property name="vscrollbar_policy">automatic</property>
+                            <property name="shadow_type">etched-in</property>
+                            <child>
+                              <object class="PsppireVarView" id="cols">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="headers_visible">False</property>
+                                <property name="headers_clickable">False</property>
+                              </object>
+                            </child>
                           </object>
                         </child>
                       </object>
                     </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label2">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="label" translatable="yes">_Columns</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">cols</property>
+                      </object>
+                    </child>
                   </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                  </packing>
                 </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label2">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label" translatable="yes">Columns</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkScrolledWindow" id="scrolledwindow1">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="hscrollbar_policy">never</property>
-                <property name="vscrollbar_policy">automatic</property>
-                <property name="shadow_type">etched-in</property>
                 <child>
-                  <object class="PsppireDictView" id="dict-treeview">
+                  <object class="GtkScrolledWindow" id="scrolledwindow1">
                     <property name="visible">True</property>
-                    <property name="headers_visible">False</property>
+                    <property name="can_focus">True</property>
+                    <property name="hscrollbar_policy">never</property>
+                    <property name="vscrollbar_policy">automatic</property>
+                    <property name="shadow_type">etched-in</property>
+                    <child>
+                      <object class="PsppireDictView" id="dict-treeview">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="headers_visible">False</property>
+                        <property name="headers_clickable">False</property>
+                      </object>
+                    </child>
                   </object>
+                  <packing>
+                    <property name="bottom_attach">2</property>
+                  </packing>
                 </child>
-              </object>
-              <packing>
-                <property name="bottom_attach">2</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkHButtonBox" id="hbuttonbox3">
-                <property name="visible">True</property>
-                <property name="layout_style">spread</property>
                 <child>
-                  <object class="GtkButton" id="format-button">
-                    <property name="label" translatable="yes">Format...</property>
+                  <object class="GtkHButtonBox" id="hbuttonbox3">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="receives_default">False</property>
+                    <property name="layout_style">spread</property>
+                    <child>
+                      <object class="GtkButton" id="format-button">
+                        <property name="label" translatable="yes">_Format...</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="use_underline">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="stats-button">
+                        <property name="label" translatable="yes">_Statistics...</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="use_underline">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="cell-button">
+                        <property name="label" translatable="yes">Ce_lls...</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="use_underline">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
                   </object>
                   <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">0</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                    <property name="y_options"></property>
+                    <property name="y_padding">5</property>
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkButton" id="stats-button">
-                    <property name="label" translatable="yes">Statistics...</property>
+                  <object class="PsppireSelector" id="row-selector">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="receives_default">False</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="border_width">5</property>
+                    <property name="source_widget">dict-treeview</property>
+                    <property name="dest_widget">rows</property>
                   </object>
                   <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="x_options"></property>
+                    <property name="y_options"></property>
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkButton" id="cell-button">
-                    <property name="label" translatable="yes">Cells...</property>
+                  <object class="PsppireSelector" id="col-selector">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="receives_default">False</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="border_width">5</property>
+                    <property name="source_widget">dict-treeview</property>
+                    <property name="dest_widget">cols</property>
                   </object>
                   <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">2</property>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="x_options"></property>
+                    <property name="y_options"></property>
                   </packing>
                 </child>
               </object>
-              <packing>
-                <property name="right_attach">3</property>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <object class="PsppireSelector" id="row-selector">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="border_width">5</property>
-                <property name="source_widget">dict-treeview</property>
-                <property name="dest_widget">rows</property>
-              </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="x_options"></property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <object class="PsppireSelector" id="col-selector">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="border_width">5</property>
-                <property name="source_widget">dict-treeview</property>
-                <property name="dest_widget">cols</property>
-              </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-                <property name="x_options"></property>
-                <property name="y_options"></property>
-              </packing>
             </child>
           </object>
           <packing>
             <property name="visible">True</property>
             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
             <property name="orientation">vertical</property>
+            <property name="spacing">5</property>
             <child>
-              <object class="GtkCheckButton" id="print-tables">
-                <property name="label" translatable="yes">Print tables</property>
+              <object class="GtkVButtonBox" id="vbuttonbox1">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">False</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="draw_indicator">True</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkCheckButton" id="print-tables">
+                    <property name="label" translatable="yes">Print tables</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="pivot">
+                    <property name="label" translatable="yes">Pivot</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="ascending">
+                    <property name="label" translatable="yes">Ascending</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
               </object>
               <packing>
                 <property name="position">0</property>
               </packing>
             </child>
-            <child>
-              <object class="GtkCheckButton" id="pivot">
-                <property name="label" translatable="yes">Pivot</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">False</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="draw_indicator">True</property>
-              </object>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkCheckButton" id="ascending">
-                <property name="label" translatable="yes">Ascending</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">False</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="draw_indicator">True</property>
-              </object>
-              <packing>
-                <property name="position">2</property>
-              </packing>
-            </child>
             <child>
               <object class="GtkFrame" id="Labeling">
                 <property name="visible">True</property>
                           <object class="GtkRadioButton" id="radiobutton1">
                             <property name="label" translatable="yes">Label</property>
                             <property name="visible">True</property>
-                            <property name="can_focus">False</property>
+                            <property name="can_focus">True</property>
                             <property name="receives_default">False</property>
+                            <property name="active">True</property>
                             <property name="draw_indicator">True</property>
                           </object>
                           <packing>
                           <object class="GtkRadioButton" id="radiobutton2">
                             <property name="label" translatable="yes">No label</property>
                             <property name="visible">True</property>
-                            <property name="can_focus">False</property>
+                            <property name="can_focus">True</property>
                             <property name="receives_default">False</property>
                             <property name="draw_indicator">True</property>
                             <property name="group">radiobutton1</property>
                           <object class="GtkRadioButton" id="radiobutton3">
                             <property name="label" translatable="yes">Suppress value labels</property>
                             <property name="visible">True</property>
-                            <property name="can_focus">False</property>
+                            <property name="can_focus">True</property>
                             <property name="receives_default">False</property>
                             <property name="draw_indicator">True</property>
                             <property name="group">radiobutton1</property>
                 </child>
               </object>
               <packing>
-                <property name="position">3</property>
+                <property name="padding">5</property>
+                <property name="position">1</property>
               </packing>
             </child>
           </object>
           <packing>
+            <property name="padding">5</property>
             <property name="position">0</property>
           </packing>
         </child>
                 <property name="can_focus">False</property>
                 <property name="hscrollbar_policy">never</property>
                 <property name="vscrollbar_policy">automatic</property>
+                <property name="shadow_type">in</property>
                 <child>
                   <object class="GtkTreeView" id="cell-view">
                     <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="hscrollbar_policy">never</property>
                 <property name="vscrollbar_policy">automatic</property>
+                <property name="shadow_type">in</property>
                 <child>
                   <object class="GtkTreeView" id="stats-view">
                     <property name="width_request">128</property>
index 04e738f23b335bca9b413eecb1b8b7a04bff3c2a..b7d0ce2d27c25eef7d4874e1ef5a178b240fadb3 100644 (file)
@@ -57,7 +57,7 @@
 
 #include <gtk/gtk.h>
 #include "customentry.h"
-
+#include "helper.h"
 
 static void psppire_custom_entry_class_init          (PsppireCustomEntryClass *klass);
 static void psppire_custom_entry_init                (PsppireCustomEntry      *ce);
index 012605e534fedbc68345f284479fca1d6a7eb65d..985d670829457f046cc8216488cae61ae2bd5821 100644 (file)
             <property name="label" translatable="yes">_Compute...</property>
           </object>
         </child>
+        <child>
+          <object class="GtkAction" id="transform_count">
+            <property name="name">transform_count</property>
+            <property name="label" translatable="yes">Cou_nt...</property>
+          </object>
+        </child>
         <child>
           <object class="GtkAction" id="transform_rank">
             <property name="name">transform_rank</property>
             <property name="label" translatable="yes">Ran_k Cases...</property>
           </object>
         </child>
+        <child>
+          <object class="GtkAction" id="transform_autorecode">
+            <property name="name">transform_autorecode</property>
+            <property name="label" translatable="yes">Auto_matic Recode...</property>
+          </object>
+        </child>
         <child>
           <object class="GtkAction" id="transform_recode-same">
             <property name="name">transform_recode-same</property>
             <property name="label" translatable="yes">Bivariate _Correlation...</property>
           </object>
         </child>
+        <child>
+          <object class="GtkAction" id="k-means">
+            <property name="name">k-means</property>
+            <property name="label" translatable="yes">_K-Means Cluster...</property>
+          </object>
+        </child>
         <child>
           <object class="GtkAction" id="factor-analysis">
             <property name="name">factor-analysis</property>
             <property name="label" translatable="yes">_Binomial...</property>
           </object>
         </child>
+        <child>
+          <object class="GtkAction" id="runs">
+            <property name="name">runs</property>
+            <property name="label" translatable="yes">R_uns...</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkAction" id="ks-one-sample">
+            <property name="name">ks-one-sample</property>
+            <property name="label" translatable="yes">1-Sample _K-S...</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkAction" id="two-related-samples">
+            <property name="name">"two-related-samples"></property>
+            <property name="label" translatable="yes">2 _Related Samples...</property>
+          </object>
+        </child>
         <child>
           <object class="GtkAction" id="k-related-samples">
             <property name="name">"k-related-samples"></property>
         </menu>
         <menu action="transform">
           <menuitem action="transform_compute"/>
+          <menuitem action="transform_count"/>
           <menuitem action="transform_rank"/>
+          <menuitem action="transform_autorecode"/>
           <separator/>
           <menuitem action="transform_recode-same"/>
           <menuitem action="transform_recode-different"/>
             <menuitem action="oneway-anova"/>
           </menu>
           <menuitem action="correlation"/>
+          <menuitem action="k-means"/>
           <menuitem action="factor-analysis"/>
           <menuitem action="reliability"/>
           <menuitem action="linear-regression"/>
           <menu action="non-parametrics">
             <menuitem action="chi-square"/>
             <menuitem action="binomial"/>
+            <menuitem action="runs"/>
+            <menuitem action="ks-one-sample"/>
+            <menuitem action="two-related-samples"/>
             <menuitem action="k-related-samples"/>
           </menu>
           <menuitem action="roc-curve"/>
index c1831db387ca067af71a2dc15332e585c43fa0ea..70fef5df1ac317572e00a667597a78f200f3767f 100644 (file)
         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
         <property name="spacing">2</property>
         <child>
-          <object class="GtkVBox" id="vbox29">
+          <object class="GtkAlignment" id="alignment1">
             <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="orientation">vertical</property>
+            <property name="top_padding">5</property>
+            <property name="bottom_padding">5</property>
+            <property name="left_padding">5</property>
             <child>
-              <object class="GtkHBox" id="hbox24">
+              <object class="GtkVBox" id="vbox29">
                 <property name="visible">True</property>
                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="orientation">vertical</property>
                 <child>
-                  <object class="GtkScrolledWindow" id="scrolledwindow16">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="hscrollbar_policy">never</property>
-                    <property name="vscrollbar_policy">automatic</property>
-                    <property name="shadow_type">etched-in</property>
-                    <child>
-                      <object class="PsppireDictView" id="all-variables">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="headers_visible">False</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkAlignment" id="alignment19">
+                  <object class="GtkHBox" id="hbox24">
                     <property name="visible">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="yalign">0.25</property>
-                    <property name="xscale">0</property>
-                    <property name="yscale">0</property>
                     <child>
-                      <object class="PsppireSelector" id="stat-var-selector">
+                      <object class="GtkScrolledWindow" id="scrolledwindow16">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="border_width">5</property>
-                        <property name="source_widget">all-variables</property>
-                        <property name="dest_widget">stat-variables</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkVBox" id="vbox30">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="orientation">vertical</property>
-                    <child>
-                      <object class="GtkVBox" id="vbox31">
-                        <property name="visible">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="orientation">vertical</property>
+                        <property name="hscrollbar_policy">never</property>
+                        <property name="vscrollbar_policy">automatic</property>
+                        <property name="shadow_type">etched-in</property>
                         <child>
-                          <object class="GtkLabel" id="label37">
+                          <object class="PsppireDictView" id="all-variables">
                             <property name="visible">True</property>
+                            <property name="can_focus">True</property>
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="xalign">0</property>
-                            <property name="label" translatable="yes">Variables:</property>
-                            <property name="wrap_mode">word-char</property>
+                            <property name="headers_visible">False</property>
+                            <property name="headers_clickable">False</property>
                           </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="position">0</property>
-                          </packing>
                         </child>
+                      </object>
+                      <packing>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkAlignment" id="alignment19">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="yalign">0.25</property>
+                        <property name="xscale">0</property>
+                        <property name="yscale">0</property>
                         <child>
-                          <object class="GtkScrolledWindow" id="scrolledwindow17">
+                          <object class="PsppireSelector" id="stat-var-selector">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="hscrollbar_policy">never</property>
-                            <property name="vscrollbar_policy">automatic</property>
-                            <property name="shadow_type">etched-in</property>
-                            <child>
-                              <object class="PsppireVarView" id="stat-variables">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="headers_visible">False</property>
-                              </object>
-                            </child>
+                            <property name="border_width">5</property>
+                            <property name="source_widget">all-variables</property>
+                            <property name="dest_widget">stat-variables</property>
                           </object>
-                          <packing>
-                            <property name="position">1</property>
-                          </packing>
                         </child>
                       </object>
                       <packing>
-                        <property name="padding">5</property>
-                        <property name="position">0</property>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkVBox" id="vbox28">
+                      <object class="GtkVBox" id="vbox30">
                         <property name="visible">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                         <property name="orientation">vertical</property>
                         <child>
-                          <object class="GtkLabel" id="label36">
+                          <object class="GtkFrame" id="frame1">
                             <property name="visible">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="xalign">0</property>
-                            <property name="label" translatable="yes">Statistics:</property>
-                            <property name="wrap_mode">word-char</property>
+                            <property name="label_xalign">0</property>
+                            <property name="shadow_type">none</property>
+                            <child>
+                              <object class="GtkAlignment" id="alignment2">
+                                <property name="visible">True</property>
+                                <property name="left_padding">12</property>
+                                <child>
+                                  <object class="GtkScrolledWindow" id="scrolledwindow17">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                    <property name="hscrollbar_policy">never</property>
+                                    <property name="vscrollbar_policy">automatic</property>
+                                    <property name="shadow_type">etched-in</property>
+                                    <child>
+                                      <object class="PsppireVarView" id="stat-variables">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                        <property name="headers_visible">False</property>
+                                        <property name="headers_clickable">False</property>
+                                      </object>
+                                    </child>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                            <child type="label">
+                              <object class="GtkLabel" id="label1">
+                                <property name="visible">True</property>
+                                <property name="label" translatable="yes">_Variables:</property>
+                                <property name="use_markup">True</property>
+                                <property name="use_underline">True</property>
+                                <property name="mnemonic_widget">stat-variables</property>
+                              </object>
+                            </child>
                           </object>
                           <packing>
-                            <property name="expand">False</property>
                             <property name="position">0</property>
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkScrolledWindow" id="scrolledwindow14">
+                          <object class="GtkFrame" id="frame2">
                             <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="hscrollbar_policy">automatic</property>
-                            <property name="vscrollbar_policy">automatic</property>
-                            <property name="shadow_type">etched-in</property>
+                            <property name="label_xalign">0</property>
+                            <property name="shadow_type">none</property>
                             <child>
-                              <object class="GtkTreeView" id="statistics">
-                                <property name="height_request">200</property>
+                              <object class="GtkAlignment" id="alignment3">
                                 <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="headers_visible">False</property>
+                                <property name="left_padding">12</property>
+                                <child>
+                                  <object class="GtkScrolledWindow" id="scrolledwindow14">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                    <property name="hscrollbar_policy">automatic</property>
+                                    <property name="vscrollbar_policy">automatic</property>
+                                    <property name="shadow_type">etched-in</property>
+                                    <child>
+                                      <object class="GtkTreeView" id="statistics">
+                                        <property name="height_request">200</property>
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                        <property name="headers_visible">False</property>
+                                      </object>
+                                    </child>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                            <child type="label">
+                              <object class="GtkLabel" id="label2">
+                                <property name="visible">True</property>
+                                <property name="label" translatable="yes">S_tatistics:</property>
+                                <property name="use_markup">True</property>
+                                <property name="use_underline">True</property>
+                                <property name="mnemonic_widget">statistics</property>
                               </object>
                             </child>
                           </object>
                         </child>
                       </object>
                       <packing>
-                        <property name="position">1</property>
+                        <property name="padding">5</property>
+                        <property name="position">2</property>
                       </packing>
                     </child>
                   </object>
                   <packing>
-                    <property name="padding">5</property>
-                    <property name="position">2</property>
+                    <property name="position">0</property>
                   </packing>
                 </child>
-              </object>
-              <packing>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFrame" id="frame11">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label_xalign">0</property>
                 <child>
-                  <object class="GtkAlignment" id="alignment20">
+                  <object class="GtkFrame" id="frame11">
                     <property name="visible">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="left_padding">12</property>
+                    <property name="label_xalign">0</property>
                     <child>
-                      <object class="GtkVButtonBox" id="vbuttonbox5">
+                      <object class="GtkAlignment" id="alignment20">
                         <property name="visible">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="left_padding">12</property>
                         <child>
-                          <object class="GtkCheckButton" id="exclude_missing_listwise">
-                            <property name="label" translatable="yes">Exclude entire case if any selected variable is missing</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkCheckButton" id="include_user_missing">
-                            <property name="label" translatable="yes">Include user-missing data in analysis</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkCheckButton" id="save_z_scores">
-                            <property name="label" translatable="yes">Save Z-scores of selected variables as new variables</property>
+                          <object class="GtkVButtonBox" id="vbuttonbox5">
                             <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="draw_indicator">True</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <object class="GtkCheckButton" id="exclude_missing_listwise">
+                                <property name="label" translatable="yes">_Exclude entire case if any selected variable is missing</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="include_user_missing">
+                                <property name="label" translatable="yes">_Include user-missing data in analysis</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="save_z_scores">
+                                <property name="label" translatable="yes">Save _Z-scores of selected variables as new variables</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
                           </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">2</property>
-                          </packing>
                         </child>
                       </object>
                     </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label40">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="label" translatable="yes">Options:</property>
+                      </object>
+                    </child>
                   </object>
-                </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label40">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label" translatable="yes">Options:</property>
-                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">1</property>
+                  </packing>
                 </child>
               </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="position">1</property>
-              </packing>
             </child>
           </object>
           <packing>
index c10fa597c18fae9a5f562b5d9f4320bb82e4c781..26702450ef9e1153d22e0075e768c2127594a676 100644 (file)
@@ -28,7 +28,7 @@
 #include "psppire-data-window.h"
 #include "psppire-var-view.h"
 
-#include "widget-io.h"
+#include "psppire-scanf.h"
 
 #include "executor.h"
 #include "helper.h"
@@ -340,10 +340,18 @@ factor_dialog (PsppireDataWindow *dw)
 
   {
     GtkWidget *hbox = get_widget_assert (fd.xml, "hbox6");
-    GtkWidget *eigenvalue_extraction = widget_scanf (_("Eigenvalues over %4.2f times the mean eigenvalue"), &fd.mineigen);
+    GtkWidget *eigenvalue_extraction ;
 
-    fd.nfactors_toggle = get_widget_assert (fd.xml, "nfactors-radiobutton");
     fd.mineigen_toggle = get_widget_assert (fd.xml, "mineigen-radiobutton");
+
+    eigenvalue_extraction = psppire_scanf_new (_("_Eigenvalues over %4.2f times the mean eigenvalue"), &fd.mineigen);
+
+    g_object_set (eigenvalue_extraction,
+                 "use-underline", TRUE,
+                 "mnemonic-widget", fd.mineigen_toggle,
+                 NULL);
+
+    fd.nfactors_toggle = get_widget_assert (fd.xml, "nfactors-radiobutton");
     fd.n_factors = get_widget_assert (fd.xml, "spinbutton-nfactors");
     fd.extract_iterations = get_widget_assert (fd.xml, "spinbutton-extract-iterations");
     fd.covariance_toggle = get_widget_assert (fd.xml,  "covariance-radiobutton");
index 6782f6bf7e4ccae228cc0e7d5e3199382eb47e9e..9705f891519a7cc499c7606965db1893c72c3c9c 100644 (file)
                 </child>
               </object>
               <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
                 <property name="position">1</property>
               </packing>
             </child>
                 <child type="label">
                   <object class="GtkLabel" id="label1">
                     <property name="visible">True</property>
-                    <property name="label" translatable="yes">Variables:</property>
+                    <property name="label" translatable="yes">_Variables:</property>
                     <property name="use_markup">True</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">psppire-var-view1</property>
                   </object>
                 </child>
               </object>
                     <child>
                       <object class="GtkLabel" id="label5">
                         <property name="visible">True</property>
-                        <property name="label" translatable="yes">Method: </property>
+                        <property name="label" translatable="yes">_Method: </property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">combobox1</property>
                       </object>
                       <packing>
                         <property name="expand">False</property>
                                 <property name="layout_style">spread</property>
                                 <child>
                                   <object class="GtkRadioButton" id="correlations-radiobutton">
-                                    <property name="label" translatable="yes">Correlation matrix</property>
+                                    <property name="label" translatable="yes">Co_rrelation matrix</property>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">False</property>
+                                    <property name="use_underline">True</property>
                                     <property name="draw_indicator">True</property>
                                   </object>
                                   <packing>
                                 </child>
                                 <child>
                                   <object class="GtkRadioButton" id="covariance-radiobutton">
-                                    <property name="label" translatable="yes">Covariance matrix</property>
+                                    <property name="label" translatable="yes">Co_variance matrix</property>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">False</property>
+                                    <property name="use_underline">True</property>
                                     <property name="draw_indicator">True</property>
                                     <property name="group">correlations-radiobutton</property>
                                   </object>
                                 <property name="layout_style">spread</property>
                                 <child>
                                   <object class="GtkCheckButton" id="unrotated-button">
-                                    <property name="label" translatable="yes">Unrotated factor solution</property>
+                                    <property name="label" translatable="yes">_Unrotated factor solution</property>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">False</property>
+                                    <property name="use_underline">True</property>
                                     <property name="draw_indicator">True</property>
                                   </object>
                                   <packing>
                                 </child>
                                 <child>
                                   <object class="GtkCheckButton" id="scree-button">
-                                    <property name="label" translatable="yes">Scree plot</property>
+                                    <property name="label" translatable="yes">_Scree plot</property>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">False</property>
+                                    <property name="use_underline">True</property>
                                     <property name="draw_indicator">True</property>
                                   </object>
                                   <packing>
                                   <object class="GtkLabel" id="label7">
                                     <property name="visible">True</property>
                                     <property name="xalign">0</property>
-                                    <property name="label" translatable="yes">Number of factors:</property>
+                                    <property name="label" translatable="yes">_Number of factors:</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">nfactors-radiobutton</property>
                                   </object>
                                   <packing>
                                     <property name="position">1</property>
                     <child>
                       <object class="GtkLabel" id="label6">
                         <property name="visible">True</property>
-                        <property name="label" translatable="yes">Maximum iterations for convergence:</property>
+                        <property name="label" translatable="yes">Ma_ximum iterations for convergence:</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">spinbutton-extract-iterations</property>
                       </object>
                       <packing>
                         <property name="position">0</property>
                     <child>
                       <object class="GtkLabel" id="label13">
                         <property name="visible">True</property>
-                        <property name="label" translatable="yes">Maximum iterations for convergence:</property>
+                        <property name="label" translatable="yes">Ma_ximum iterations for convergence:</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">spinbutton-rot-iterations</property>
                       </object>
                       <packing>
                         <property name="position">0</property>
index a83c4f6e04e75fc1e998596771430488d79a8310..4a1b356c04abd20ab44d30450b48604896f2b66f 100644 (file)
         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
         <property name="spacing">2</property>
         <child>
-          <object class="GtkVBox" id="vbox1">
+          <object class="GtkAlignment" id="alignment1">
             <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="orientation">vertical</property>
+            <property name="top_padding">5</property>
+            <property name="bottom_padding">5</property>
+            <property name="left_padding">5</property>
             <child>
               <object class="GtkHBox" id="hbox2">
                 <property name="visible">True</property>
@@ -36,6 +37,7 @@
                         <property name="can_focus">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                         <property name="headers_visible">False</property>
+                        <property name="headers_clickable">False</property>
                       </object>
                     </child>
                   </object>
@@ -44,7 +46,7 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkAlignment" id="alignment1">
+                  <object class="GtkAlignment" id="alignment7">
                     <property name="visible">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                     <property name="yalign">0.05000000074505806</property>
@@ -57,8 +59,8 @@
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                         <property name="no_show_all">True</property>
                         <property name="border_width">5</property>
-                       <property name="source_widget">dict-treeview</property>
-                       <property name="dest_widget">var-treeview</property>
+                        <property name="source_widget">dict-treeview</property>
+                        <property name="dest_widget">var-treeview</property>
                       </object>
                     </child>
                   </object>
@@ -73,6 +75,7 @@
                     <property name="visible">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                     <property name="orientation">vertical</property>
+                    <property name="spacing">5</property>
                     <child>
                       <object class="GtkFrame" id="frame3">
                         <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="hscrollbar_policy">automatic</property>
                             <property name="vscrollbar_policy">automatic</property>
+                            <property name="shadow_type">in</property>
                             <child>
                               <object class="PsppireVarView" id="var-treeview">
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                                 <property name="headers_visible">False</property>
+                                <property name="headers_clickable">False</property>
                               </object>
                             </child>
                           </object>
                           <object class="GtkLabel" id="label1">
                             <property name="visible">True</property>
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="label" translatable="yes">Variable(s):</property>
+                            <property name="label" translatable="yes">_Variable(s):</property>
                             <property name="use_markup">True</property>
+                            <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">var-treeview</property>
                           </object>
                         </child>
                       </object>
                       <packing>
                         <property name="expand">False</property>
+                        <property name="fill">False</property>
                         <property name="position">0</property>
                       </packing>
                     </child>
                           <object class="GtkLabel" id="label2">
                             <property name="visible">True</property>
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="label" translatable="yes">Statistics:</property>
+                            <property name="label" translatable="yes">_Statistics:</property>
                             <property name="use_markup">True</property>
+                            <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">stats-treeview</property>
                           </object>
                         </child>
                       </object>
                     </child>
                     <child>
                       <object class="GtkCheckButton" id="include_missing">
-                        <property name="label" translatable="yes">Include missing values</property>
+                        <property name="label" translatable="yes">Include _missing values</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">False</property>
+                        <property name="use_underline">True</property>
                         <property name="draw_indicator">True</property>
                       </object>
                       <packing>
                         <property name="position">2</property>
                       </packing>
                     </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkHBox" id="hbox3">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <child>
-                  <object class="GtkHBox" id="hbox4">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="spacing">5</property>
-                    <property name="homogeneous">True</property>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <object class="GtkButton" id="charts-button">
-                        <property name="label" translatable="yes">Charts...</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                      </object>
-                      <packing>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
                     <child>
-                      <object class="GtkButton" id="tables-button">
-                        <property name="label" translatable="yes">Frequency Tables...</property>
+                      <object class="GtkHButtonBox" id="hbuttonbox1">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <child>
+                          <object class="GtkButton" id="charts-button">
+                            <property name="label" translatable="yes">Charts...</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkButton" id="tables-button">
+                            <property name="label" translatable="yes">Frequency Tables...</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
                       </object>
                       <packing>
-                        <property name="position">2</property>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">3</property>
                       </packing>
                     </child>
                   </object>
                   <packing>
                     <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="padding">5</property>
-                    <property name="pack_type">end</property>
-                    <property name="position">1</property>
+                    <property name="position">2</property>
                   </packing>
                 </child>
               </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="padding">5</property>
-                <property name="position">1</property>
-              </packing>
             </child>
           </object>
           <packing>
         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
         <property name="spacing">2</property>
         <child>
-          <object class="GtkVBox" id="vbox3">
+          <object class="GtkAlignment" id="alignment2">
             <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="orientation">vertical</property>
+            <property name="top_padding">5</property>
+            <property name="bottom_padding">5</property>
+            <property name="left_padding">5</property>
             <child>
-              <object class="GtkFrame" id="frame5">
+              <object class="GtkVBox" id="vbox3">
                 <property name="visible">True</property>
                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label_xalign">0</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">5</property>
                 <child>
-                  <object class="GtkAlignment" id="alignment2">
+                  <object class="GtkFrame" id="frame5">
                     <property name="visible">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="left_padding">12</property>
+                    <property name="label_xalign">0</property>
                     <child>
-                      <object class="GtkVButtonBox" id="vbuttonbox2">
+                      <object class="GtkAlignment" id="alignment3">
                         <property name="visible">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="orientation">vertical</property>
-                        <property name="homogeneous">True</property>
-                        <child>
-                          <object class="GtkRadioButton" id="always">
-                            <property name="label" translatable="yes">Always</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="active">True</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
+                        <property name="left_padding">12</property>
                         <child>
-                          <object class="GtkRadioButton" id="never">
-                            <property name="label" translatable="yes">Never</property>
+                          <object class="GtkVButtonBox" id="vbuttonbox2">
                             <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="draw_indicator">True</property>
-                            <property name="group">always</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkHBox" id="hbox5">
-                            <property name="visible">True</property>
+                            <property name="orientation">vertical</property>
+                            <property name="homogeneous">True</property>
                             <child>
-                              <object class="GtkRadioButton" id="limit">
-                                <property name="label" translatable="yes">If no more than </property>
+                              <object class="GtkRadioButton" id="always">
+                                <property name="label" translatable="yes">Always</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="active">True</property>
                                 <property name="draw_indicator">True</property>
-                                <property name="group">always</property>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkSpinButton" id="limit-spin">
+                              <object class="GtkRadioButton" id="never">
+                                <property name="label" translatable="yes">Never</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK</property>
-                                <property name="invisible_char">&#x25CF;</property>
-                                <property name="adjustment">adjustment1</property>
-                                <property name="numeric">True</property>
-                                <property name="update_policy">if-valid</property>
+                                <property name="receives_default">False</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="draw_indicator">True</property>
+                                <property name="group">always</property>
                               </object>
                               <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
                                 <property name="position">1</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkLabel" id="label4">
+                              <object class="GtkHBox" id="hbox5">
                                 <property name="visible">True</property>
-                                <property name="label" translatable="yes">values</property>
+                                <child>
+                                  <object class="GtkRadioButton" id="limit">
+                                    <property name="label" translatable="yes">If no more than </property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">False</property>
+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                    <property name="draw_indicator">True</property>
+                                    <property name="group">always</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkSpinButton" id="limit-spin">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK</property>
+                                    <property name="invisible_char">&#x25CF;</property>
+                                    <property name="adjustment">adjustment1</property>
+                                    <property name="numeric">True</property>
+                                    <property name="update_policy">if-valid</property>
+                                  </object>
+                                  <packing>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel" id="label4">
+                                    <property name="visible">True</property>
+                                    <property name="label" translatable="yes">values</property>
+                                  </object>
+                                  <packing>
+                                    <property name="position">2</property>
+                                  </packing>
+                                </child>
                               </object>
                               <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
                                 <property name="position">2</property>
                               </packing>
                             </child>
                           </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">2</property>
-                          </packing>
                         </child>
                       </object>
                     </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label5">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="label" translatable="yes">Display frequency tables</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                    </child>
                   </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">0</property>
+                  </packing>
                 </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label5">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label" translatable="yes">Display frequency tables</property>
-                    <property name="use_markup">True</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFrame" id="frame7">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label_xalign">0</property>
                 <child>
-                  <object class="GtkAlignment" id="alignment3">
+                  <object class="GtkFrame" id="frame7">
                     <property name="visible">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="left_padding">12</property>
+                    <property name="label_xalign">0</property>
                     <child>
-                      <object class="GtkVButtonBox" id="vbuttonbox1">
+                      <object class="GtkAlignment" id="alignment8">
                         <property name="visible">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="orientation">vertical</property>
-                        <property name="homogeneous">True</property>
-                        <child>
-                          <object class="GtkRadioButton" id="avalue">
-                            <property name="label" translatable="yes">Ascending value</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="active">True</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkRadioButton" id="dvalue">
-                            <property name="label" translatable="yes">Descending value</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="draw_indicator">True</property>
-                            <property name="group">avalue</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkRadioButton" id="afreq">
-                            <property name="label" translatable="yes">Ascending frequency</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="draw_indicator">True</property>
-                            <property name="group">avalue</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
+                        <property name="left_padding">12</property>
                         <child>
-                          <object class="GtkRadioButton" id="dfreq">
-                            <property name="label" translatable="yes">Descending frequency</property>
+                          <object class="GtkVButtonBox" id="vbuttonbox1">
                             <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="draw_indicator">True</property>
-                            <property name="group">avalue</property>
+                            <property name="orientation">vertical</property>
+                            <property name="homogeneous">True</property>
+                            <child>
+                              <object class="GtkRadioButton" id="avalue">
+                                <property name="label" translatable="yes">Ascending value</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="active">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkRadioButton" id="dvalue">
+                                <property name="label" translatable="yes">Descending value</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="draw_indicator">True</property>
+                                <property name="group">avalue</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkRadioButton" id="afreq">
+                                <property name="label" translatable="yes">Ascending frequency</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="draw_indicator">True</property>
+                                <property name="group">avalue</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkRadioButton" id="dfreq">
+                                <property name="label" translatable="yes">Descending frequency</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="draw_indicator">True</property>
+                                <property name="group">avalue</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">3</property>
+                              </packing>
+                            </child>
                           </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">3</property>
-                          </packing>
                         </child>
                       </object>
                     </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label6">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="label" translatable="yes">Order by</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                    </child>
                   </object>
-                </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label6">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label" translatable="yes">Order by</property>
-                    <property name="use_markup">True</property>
-                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">1</property>
+                  </packing>
                 </child>
               </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="position">1</property>
-              </packing>
             </child>
           </object>
           <packing>
-            <property name="expand">False</property>
             <property name="position">0</property>
           </packing>
         </child>
index aaadefc2b36b0c60c21545ed88565f962b69adea..1015fda89811d0e826101da7765b1c26eb23c7fd 100644 (file)
@@ -48,8 +48,7 @@ about_new (GtkMenuItem *m, GtkWindow *parent)
 
   gtk_window_set_icon_name (GTK_WINDOW (about), "psppicon");
 
-  gtk_about_dialog_set_website (GTK_ABOUT_DIALOG (about),
-                               "http://www.gnu.org/software/pspp");
+  gtk_about_dialog_set_website (GTK_ABOUT_DIALOG (about), PACKAGE_URL);
 
   gtk_about_dialog_set_version (GTK_ABOUT_DIALOG (about),
                                bare_version);
@@ -98,7 +97,7 @@ reference_manual (GtkMenuItem *menu, gpointer data)
       msg (ME, _("Cannot open reference manual: %s.  The PSPP user manual is "
                  "also available at %s"),
                   err->message,
-                  "http://www.gnu.org/software/pspp/documentation.html");
+                  PACKAGE_URL "documentation.html");
     }
 
   g_free (cmd);
diff --git a/src/ui/gui/k-means-dialog.c b/src/ui/gui/k-means-dialog.c
new file mode 100644 (file)
index 0000000..0b2f00f
--- /dev/null
@@ -0,0 +1,162 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  Free Software Foundation
+
+   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 "dialog-common.h"
+#include <ui/syntax-gen.h>
+#include <libpspp/str.h>
+
+#include "k-means-dialog.h"
+#include "psppire-selector.h"
+#include "psppire-dictview.h"
+#include "psppire-dialog.h"
+
+#include "psppire-data-window.h"
+#include "psppire-var-view.h"
+
+#include "executor.h"
+#include "helper.h"
+
+#include <gtk/gtk.h>
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+
+
+
+struct k_means
+{
+  GtkBuilder *xml;
+  PsppireDict *dict;
+
+  GtkWidget *variables;
+  PsppireDataWindow *de ;
+
+  GtkWidget *entry;
+};
+
+static char * generate_syntax (const struct k_means *rd);
+
+
+static void
+refresh (struct k_means *fd)
+{
+  GtkTreeModel *liststore =
+    gtk_tree_view_get_model (GTK_TREE_VIEW (fd->variables));
+  gtk_list_store_clear (GTK_LIST_STORE (liststore));
+
+  gtk_entry_set_text (GTK_ENTRY (fd->entry), "");
+}
+
+
+static gboolean
+dialog_state_valid (gpointer data)
+{
+  struct k_means *fd = data;
+
+  GtkTreeModel *liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (fd->variables));
+
+  if  (gtk_tree_model_iter_n_children (liststore, NULL) < 2)
+    return FALSE;
+
+  if (atoi (gtk_entry_get_text (GTK_ENTRY (fd->entry))) < 2)
+    return FALSE;
+
+  return TRUE;
+}
+
+
+/* Pops up the K_Means dialog box */
+void
+k_means_dialog (PsppireDataWindow *dw)
+{
+  struct k_means fd;
+  gint response;
+
+  PsppireVarStore *vs;
+
+  GtkWidget *dialog ;
+  GtkWidget *source ;
+
+  fd.xml = builder_new ("k-means.ui");
+
+  dialog = get_widget_assert   (fd.xml, "k-means-dialog");
+  source = get_widget_assert   (fd.xml, "dict-view");
+
+  fd.entry = get_widget_assert   (fd.xml, "entry1");
+
+  fd.de = dw;
+
+  g_signal_connect_swapped (dialog, "refresh", G_CALLBACK (refresh),  &fd);
+
+
+  fd.variables = get_widget_assert   (fd.xml, "psppire-var-view1");
+
+  g_object_get (fd.de->data_editor, "var-store", &vs, NULL);
+
+  gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (fd.de));
+
+  g_object_get (vs, "dictionary", &fd.dict, NULL);
+  g_object_set (source, "model", fd.dict,
+               "predicate", var_is_numeric,
+               NULL);
+
+  psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (dialog),
+                                     dialog_state_valid, &fd);
+
+  response = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
+
+  switch (response)
+    {
+    case GTK_RESPONSE_OK:
+      g_free (execute_syntax_string (dw, generate_syntax (&fd)));
+      break;
+    case PSPPIRE_RESPONSE_PASTE:
+      g_free (paste_syntax_to_window (generate_syntax (&fd)));
+      break;
+    default:
+      break;
+    }
+
+  g_object_unref (fd.xml);
+}
+
+
+\f
+
+static char *
+generate_syntax (const struct k_means *km)
+{
+  gchar *text;
+
+  GString *string = g_string_new ("QUICK CLUSTER ");
+
+  psppire_var_view_append_names (PSPPIRE_VAR_VIEW (km->variables), 0, string);
+
+  g_string_append_printf (string, "\n\t/CRITERIA=CLUSTERS(%d)",
+                         atoi (gtk_entry_get_text (GTK_ENTRY (km->entry))));
+
+  g_string_append (string, ".\n");
+
+  text = string->str;
+
+  g_string_free (string, FALSE);
+
+  return text;
+}
diff --git a/src/ui/gui/k-means-dialog.h b/src/ui/gui/k-means-dialog.h
new file mode 100644 (file)
index 0000000..522acbc
--- /dev/null
@@ -0,0 +1,24 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  Free Software Foundation
+
+   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/>. */
+
+#ifndef __K_MEANS_DIALOG_H
+#define __K_MEANS_DIALOG_H
+
+#include "psppire-data-window.h"
+
+void k_means_dialog (PsppireDataWindow * data);
+
+#endif
diff --git a/src/ui/gui/k-means.ui b/src/ui/gui/k-means.ui
new file mode 100644 (file)
index 0000000..be659dd
--- /dev/null
@@ -0,0 +1,150 @@
+<?xml version="1.0"?>
+<interface>
+  <!-- interface-requires psppire 0.0 -->
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="PsppireDialog" id="k-means-dialog">
+    <property name="title" translatable="yes">K-Means Cluster Analysis</property>
+    <property name="modal">True</property>
+    <property name="orientation">Vertical</property>
+    <child internal-child="hbox">
+      <object class="GtkVBox" id="dialog-hbox1">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child>
+          <object class="GtkAlignment" id="alignment1">
+            <property name="visible">True</property>
+            <property name="top_padding">5</property>
+            <property name="left_padding">5</property>
+            <property name="right_padding">5</property>
+            <child>
+              <object class="GtkTable" id="table1">
+                <property name="visible">True</property>
+                <property name="n_rows">2</property>
+                <property name="n_columns">3</property>
+                <child>
+                  <object class="PsppireSelector" id="psppire-selector1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="border_width">5</property>
+                    <property name="source_widget">dict-view</property>
+                    <property name="dest_widget">psppire-var-view1</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="x_options"></property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkScrolledWindow" id="scrolledwindow1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hscrollbar_policy">never</property>
+                    <property name="vscrollbar_policy">automatic</property>
+                    <property name="shadow_type">in</property>
+                    <child>
+                      <object class="PsppireDictView" id="dict-view">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="border_width">5</property>
+                        <property name="headers_visible">False</property>
+                        <property name="headers_clickable">False</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="bottom_attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkScrolledWindow" id="scrolledwindow2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hscrollbar_policy">automatic</property>
+                    <property name="vscrollbar_policy">automatic</property>
+                    <property name="shadow_type">in</property>
+                    <child>
+                      <object class="PsppireVarView" id="psppire-var-view1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="border_width">5</property>
+                        <property name="headers_visible">False</property>
+                        <property name="headers_clickable">False</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHBox" id="hbox1">
+                    <property name="visible">True</property>
+                    <child>
+                      <object class="GtkLabel" id="label1">
+                        <property name="visible">True</property>
+                        <property name="xalign">1</property>
+                        <property name="label" translatable="yes">N_umber of Clusters: </property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">entry1</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkEntry" id="entry1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="invisible_char">&#x25CF;</property>
+                        <property name="width_chars">0</property>
+                      </object>
+                      <packing>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="PsppireHButtonBox" id="psppire-hbuttonbox1">
+            <property name="visible">True</property>
+            <property name="border_width">5</property>
+            <property name="default">PSPPIRE_BUTTON_GOTO_MASK</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
index ec12c728cdd7b6d6300c934a4d4f0b48020b38e4..10d6fb287d0aa28e986ffac3055a839383b84dc3 100644 (file)
         <property name="orientation">vertical</property>
         <property name="spacing">2</property>
         <child>
-          <object class="GtkHBox" id="hbox1">
+          <object class="GtkAlignment" id="alignment2">
             <property name="visible">True</property>
+            <property name="top_padding">5</property>
+            <property name="left_padding">5</property>
+            <property name="right_padding">5</property>
             <child>
-              <object class="GtkScrolledWindow" id="scrolledwindow1">
+              <object class="GtkVBox" id="vbox1">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="hscrollbar_policy">automatic</property>
-                <property name="vscrollbar_policy">automatic</property>
-                <property name="shadow_type">in</property>
+                <property name="orientation">vertical</property>
                 <child>
-                  <object class="PsppireDictView" id="dict-view">
+                  <object class="GtkHBox" id="hbox1">
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="border_width">5</property>
-                    <property name="headers_visible">False</property>
-                    <property name="headers_clickable">False</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkAspectFrame" id="aspectframe1">
-                <property name="visible">True</property>
-                <property name="label_xalign">0</property>
-                <property name="label_yalign">0</property>
-                <property name="shadow_type">none</property>
-                <child>
-                  <object class="PsppireSelector" id="psppire-selector1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="border_width">5</property>
-                    <property name="source_widget">dict-view</property>
-                    <property name="dest_widget">variables-treeview</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFrame" id="frame2">
-                <property name="visible">True</property>
-                <property name="label_xalign">0</property>
-                <property name="shadow_type">none</property>
-                <child>
-                  <object class="GtkAlignment" id="alignment2">
-                    <property name="visible">True</property>
-                    <property name="left_padding">12</property>
                     <child>
-                      <object class="GtkScrolledWindow" id="scrolledwindow2">
+                      <object class="GtkScrolledWindow" id="scrolledwindow1">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="hscrollbar_policy">automatic</property>
                         <property name="vscrollbar_policy">automatic</property>
                         <property name="shadow_type">in</property>
                         <child>
-                          <object class="PsppireVarView" id="variables-treeview">
+                          <object class="PsppireDictView" id="dict-view">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="border_width">5</property>
                           </object>
                         </child>
                       </object>
-                    </child>
-                  </object>
-                </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label1">
-                    <property name="visible">True</property>
-                    <property name="label" translatable="yes">_Test Variables:</property>
-                    <property name="use_markup">True</property>
-                    <property name="use_underline">True</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkFrame" id="frame1">
-            <property name="visible">True</property>
-            <property name="label_xalign">0</property>
-            <child>
-              <object class="GtkAlignment" id="alignment1">
-                <property name="visible">True</property>
-                <property name="left_padding">12</property>
-                <child>
-                  <object class="GtkHButtonBox" id="hbuttonbox1">
-                    <property name="visible">True</property>
-                    <child>
-                      <object class="GtkCheckButton" id="friedman-checkbutton">
-                        <property name="label" translatable="yes">_Friedman</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="draw_indicator">True</property>
-                      </object>
                       <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
                         <property name="position">0</property>
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkCheckButton" id="kendal-checkbutton">
-                        <property name="label" translatable="yes">_Kendall's W</property>
+                      <object class="GtkAspectFrame" id="aspectframe1">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="draw_indicator">True</property>
+                        <property name="label_xalign">0</property>
+                        <property name="label_yalign">0</property>
+                        <property name="shadow_type">none</property>
+                        <child>
+                          <object class="PsppireSelector" id="psppire-selector1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="border_width">5</property>
+                            <property name="source_widget">dict-view</property>
+                            <property name="dest_widget">variables-treeview</property>
+                          </object>
+                        </child>
                       </object>
                       <packing>
                         <property name="expand">False</property>
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkCheckButton" id="cochran-checkbutton">
-                        <property name="label" translatable="yes">_Cochran's Q</property>
+                      <object class="GtkFrame" id="frame2">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="draw_indicator">True</property>
+                        <property name="label_xalign">0</property>
+                        <property name="shadow_type">none</property>
+                        <child>
+                          <object class="GtkAlignment" id="alignment3">
+                            <property name="visible">True</property>
+                            <property name="left_padding">12</property>
+                            <child>
+                              <object class="GtkScrolledWindow" id="scrolledwindow2">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="hscrollbar_policy">automatic</property>
+                                <property name="vscrollbar_policy">automatic</property>
+                                <property name="shadow_type">in</property>
+                                <child>
+                                  <object class="PsppireVarView" id="variables-treeview">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="border_width">5</property>
+                                    <property name="headers_visible">False</property>
+                                    <property name="headers_clickable">False</property>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                        <child type="label">
+                          <object class="GtkLabel" id="label1">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">_Test Variables:</property>
+                            <property name="use_markup">True</property>
+                            <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">variables-treeview</property>
+                          </object>
+                        </child>
                       </object>
                       <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
                         <property name="position">2</property>
                       </packing>
                     </child>
                   </object>
+                  <packing>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkFrame" id="frame1">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <child>
+                      <object class="GtkAlignment" id="alignment1">
+                        <property name="visible">True</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <object class="GtkHButtonBox" id="hbuttonbox1">
+                            <property name="visible">True</property>
+                            <child>
+                              <object class="GtkCheckButton" id="friedman-checkbutton">
+                                <property name="label" translatable="yes">_Friedman</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="kendal-checkbutton">
+                                <property name="label" translatable="yes">_Kendall's W</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="cochran-checkbutton">
+                                <property name="label" translatable="yes">_Cochran's Q</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="frame">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Test Type</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">1</property>
+                  </packing>
                 </child>
-              </object>
-            </child>
-            <child type="label">
-              <object class="GtkLabel" id="frame">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">Test Type</property>
-                <property name="use_markup">True</property>
               </object>
             </child>
           </object>
           <packing>
-            <property name="expand">False</property>
-            <property name="position">1</property>
+            <property name="position">0</property>
           </packing>
         </child>
+        <child>
+          <placeholder/>
+        </child>
         <child>
           <object class="PsppireHButtonBox" id="psppire-hbuttonbox1">
             <property name="visible">True</property>
             <property name="expand">False</property>
             <property name="fill">False</property>
             <property name="pack_type">end</property>
-            <property name="position">2</property>
+            <property name="position">1</property>
           </packing>
         </child>
       </object>
diff --git a/src/ui/gui/ks-one-sample-dialog.c b/src/ui/gui/ks-one-sample-dialog.c
new file mode 100644 (file)
index 0000000..c9a1bcb
--- /dev/null
@@ -0,0 +1,199 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  Free Software Foundation
+
+   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 <ui/syntax-gen.h>
+#include <libpspp/str.h>
+
+#include "ks-one-sample-dialog.h"
+#include "psppire-selector.h"
+#include "psppire-dictview.h"
+#include "psppire-dialog.h"
+
+#include "psppire-data-window.h"
+#include "psppire-var-view.h"
+
+#include "executor.h"
+#include "helper.h"
+#include "dialog-common.h"
+
+#include <gtk/gtk.h>
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+
+enum
+  {
+    CB_NORMAL,
+    CB_POISSON,
+    CB_UNIFORM,
+    CB_EXPONENTIAL
+  };
+
+struct ks_one_sample
+{
+  GtkBuilder *xml;
+  PsppireDict *dict;
+
+  GtkWidget *variables;
+  PsppireDataWindow *de ;
+
+  GtkWidget *cb[4];
+};
+
+static char * generate_syntax (const struct ks_one_sample *rd);
+
+
+static void
+refresh (struct ks_one_sample *fd)
+{
+  int i;
+  GtkTreeModel *liststore =
+    gtk_tree_view_get_model (GTK_TREE_VIEW (fd->variables));
+  gtk_list_store_clear (GTK_LIST_STORE (liststore));
+
+  for (i = 0; i < 4; ++i)
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->cb[i]), FALSE);
+}
+
+
+static gboolean
+dialog_state_valid (gpointer data)
+{
+  int i;
+  struct ks_one_sample *fd = data;
+
+  GtkTreeModel *liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (fd->variables));
+
+  if  (gtk_tree_model_iter_n_children (liststore, NULL) < 1)
+    return FALSE;
+
+  for (i = 0; i < 4; ++i)
+    {
+      if ( TRUE == gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->cb[i])))
+       break;
+    }
+  if ( i >= 4)
+    return FALSE;
+
+
+  return TRUE;
+}
+
+
+/* Pops up the Ks_One_Sample dialog box */
+void
+ks_one_sample_dialog (PsppireDataWindow *dw)
+{
+  struct ks_one_sample fd;
+  gint response;
+
+  PsppireVarStore *vs;
+
+  GtkWidget *dialog ;
+  GtkWidget *source ;
+
+  fd.xml = builder_new ("ks-one-sample.ui");
+
+  dialog = get_widget_assert   (fd.xml, "ks-one-sample-dialog");
+  source = get_widget_assert   (fd.xml, "dict-view");
+
+  fd.cb[CB_NORMAL] = get_widget_assert (fd.xml, "checkbutton-normal");
+  fd.cb[CB_POISSON] = get_widget_assert (fd.xml, "checkbutton-poisson");
+  fd.cb[CB_UNIFORM] = get_widget_assert (fd.xml, "checkbutton-uniform");
+  fd.cb[CB_EXPONENTIAL] = get_widget_assert (fd.xml, "checkbutton-exp");
+
+  fd.de = dw;
+
+  g_signal_connect_swapped (dialog, "refresh", G_CALLBACK (refresh),  &fd);
+
+
+  fd.variables = get_widget_assert   (fd.xml, "psppire-var-view1");
+
+  g_object_get (fd.de->data_editor, "var-store", &vs, NULL);
+
+  gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (fd.de));
+
+  g_object_get (vs, "dictionary", &fd.dict, NULL);
+  g_object_set (source, "model", fd.dict,
+               "predicate", var_is_numeric,
+               NULL);
+
+  psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (dialog),
+                                     dialog_state_valid, &fd);
+
+  response = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
+
+  switch (response)
+    {
+    case GTK_RESPONSE_OK:
+      g_free (execute_syntax_string (dw, generate_syntax (&fd)));
+      break;
+    case PSPPIRE_RESPONSE_PASTE:
+      g_free (paste_syntax_to_window (generate_syntax (&fd)));
+      break;
+    default:
+      break;
+    }
+
+  g_object_unref (fd.xml);
+}
+
+
+\f
+static void
+append_fragment (GString *string, const gchar *dist, PsppireVarView *vv)
+{
+  g_string_append (string, "\n\t/KOLMOGOROV-SMIRNOV");
+
+  g_string_append (string, " ( ");
+  g_string_append (string, dist);
+  g_string_append (string, " ) = ");
+
+  psppire_var_view_append_names (vv, 0, string);
+}
+
+
+char *
+generate_syntax (const struct ks_one_sample *rd)
+{
+  gchar *text;
+
+  GString *string = g_string_new ("NPAR TEST");
+
+  if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->cb[CB_NORMAL])))
+    append_fragment (string, "NORMAL", PSPPIRE_VAR_VIEW (rd->variables));
+
+  if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->cb[CB_UNIFORM])))
+    append_fragment (string, "UNIFORM", PSPPIRE_VAR_VIEW (rd->variables));
+
+  if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->cb[CB_POISSON])))
+    append_fragment (string, "POISSON", PSPPIRE_VAR_VIEW (rd->variables));
+
+  if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->cb[CB_EXPONENTIAL])))
+    append_fragment (string, "EXPONENTIAL", PSPPIRE_VAR_VIEW (rd->variables));
+
+  g_string_append (string, ".\n");
+
+  text = string->str;
+
+  g_string_free (string, FALSE);
+
+  return text;
+}
diff --git a/src/ui/gui/ks-one-sample-dialog.h b/src/ui/gui/ks-one-sample-dialog.h
new file mode 100644 (file)
index 0000000..59f4589
--- /dev/null
@@ -0,0 +1,24 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  Free Software Foundation
+
+   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/>. */
+
+#ifndef __KS_ONE_SAMPLE_DIALOG_H
+#define __KS_ONE_SAMPLE_DIALOG_H
+
+#include "psppire-data-window.h"
+
+void ks_one_sample_dialog (PsppireDataWindow * data);
+
+#endif
diff --git a/src/ui/gui/ks-one-sample.ui b/src/ui/gui/ks-one-sample.ui
new file mode 100644 (file)
index 0000000..9386e40
--- /dev/null
@@ -0,0 +1,231 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-requires psppire 0.0 -->
+  <!-- interface-naming-policy project-wide -->
+  <object class="PsppireDialog" id="ks-one-sample-dialog">
+    <property name="title" translatable="yes">One-Sample Kolmogorov-Smirnov Test</property>
+    <property name="modal">True</property>
+    <child internal-child="hbox">
+      <object class="GtkHBox" id="dialog-hbox1">
+        <property name="visible">True</property>
+        <property name="spacing">2</property>
+        <child>
+          <object class="GtkAlignment" id="alignment1">
+            <property name="visible">True</property>
+            <property name="top_padding">5</property>
+            <property name="bottom_padding">5</property>
+            <property name="left_padding">5</property>
+            <child>
+              <object class="GtkVBox" id="vbox1">
+                <property name="visible">True</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">5</property>
+                <child>
+                  <object class="GtkHBox" id="hbox1">
+                    <property name="visible">True</property>
+                    <child>
+                      <object class="GtkScrolledWindow" id="scrolledwindow1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="hscrollbar_policy">never</property>
+                        <property name="vscrollbar_policy">automatic</property>
+                        <property name="shadow_type">in</property>
+                        <child>
+                          <object class="PsppireDictView" id="dict-view">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="border_width">5</property>
+                            <property name="headers_visible">False</property>
+                            <property name="headers_clickable">False</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkVBox" id="vbox2">
+                        <property name="visible">True</property>
+                        <property name="orientation">vertical</property>
+                        <property name="homogeneous">True</property>
+                        <child>
+                          <object class="PsppireSelector" id="psppire-selector1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="border_width">5</property>
+                            <property name="source_widget">dict-view</property>
+                            <property name="dest_widget">psppire-var-view1</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="padding">5</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkFrame" id="frame1">
+                        <property name="visible">True</property>
+                        <property name="label_xalign">0</property>
+                        <property name="shadow_type">none</property>
+                        <child>
+                          <object class="GtkAlignment" id="alignment3">
+                            <property name="visible">True</property>
+                            <property name="left_padding">12</property>
+                            <child>
+                              <object class="GtkScrolledWindow" id="scrolledwindow2">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="hscrollbar_policy">never</property>
+                                <property name="vscrollbar_policy">automatic</property>
+                                <property name="shadow_type">in</property>
+                                <child>
+                                  <object class="PsppireVarView" id="psppire-var-view1">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="border_width">5</property>
+                                    <property name="headers_visible">False</property>
+                                    <property name="headers_clickable">False</property>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                        <child type="label">
+                          <object class="GtkLabel" id="label1">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">Test _Variable List:</property>
+                            <property name="use_markup">True</property>
+                            <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">psppire-var-view1</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkFrame" id="frame2">
+                    <property name="label_xalign">0</property>
+                    <property name="visible">True</property>
+                    <child>
+                      <object class="GtkAlignment" id="alignment2">
+                        <property name="visible">True</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <object class="GtkTable" id="table1">
+                            <property name="visible">True</property>
+                            <property name="n_rows">2</property>
+                            <property name="n_columns">2</property>
+                            <child>
+                              <object class="GtkCheckButton" id="checkbutton-normal">
+                                <property name="label" translatable="yes">_Normal</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="relief">none</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="checkbutton-poisson">
+                                <property name="label" translatable="yes">_Poisson</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="checkbutton-uniform">
+                                <property name="label" translatable="yes">_Uniform</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="checkbutton-exp">
+                                <property name="label" translatable="yes">_Exponential</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label2">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Test Distribution</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="PsppireVButtonBox" id="psppire-vbuttonbox1">
+            <property name="visible">True</property>
+            <property name="border_width">5</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
index 7e9d4ee51a8960f2d52cb365076888e2eeca715e..cc5ebe3f644748d130bbe11450f3c5d021ae22f9 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPPIRE - a graphical user interface for PSPP.
-   Copyright (C) 2004, 2005, 2006, 2010  Free Software Foundation
+   Copyright (C) 2004, 2005, 2006, 2010, 2011  Free Software Foundation
 
    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
@@ -23,6 +23,7 @@
 
 #include "language/lexer/include-path.h"
 #include "libpspp/argv-parser.h"
+#include "libpspp/array.h"
 #include "libpspp/assertion.h"
 #include "libpspp/cast.h"
 #include "libpspp/copyleft.h"
@@ -216,6 +217,27 @@ static GMemVTable vtable =
     realloc
   };
 
+#ifdef __APPLE__
+/* Searches ARGV for the -psn_xxxx option that the desktop application
+   launcher passes in, and removes it if it finds it.  Returns the new value
+   of ARGC. */
+static int
+remove_psn (int argc, char **argv)
+{
+  int i;
+
+  for (i = 0; i < argc; i++)
+    {
+      if (!strncmp(argv[i], "-psn", 4))
+        {
+          remove_element (argv, argc + 1, sizeof *argv, i);
+          return argc - 1;
+        }
+    }
+  return argc;
+}
+#endif  /* __APPLE__ */
+
 int
 main (int argc, char *argv[])
 {
@@ -244,6 +266,9 @@ main (int argc, char *argv[])
       g_warning ("%s", vers);
     }
 
+#ifdef __APPLE__
+  argc = remove_psn (argc, argv);
+#endif
 
   /* Parse our own options. 
      This must come BEFORE gdk_init otherwise options such as 
diff --git a/src/ui/gui/npar-two-sample-related.c b/src/ui/gui/npar-two-sample-related.c
new file mode 100644 (file)
index 0000000..ac3bcd5
--- /dev/null
@@ -0,0 +1,170 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  Free Software Foundation
+
+   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 <gtk/gtk.h>
+
+#include "psppire-data-window.h"
+#include "psppire-selector.h"
+#include "psppire-var-view.h"
+
+#include "psppire-dict.h"
+#include "psppire-var-store.h"
+
+#include "dialog-common.h"
+#include "psppire-dialog.h"
+
+#include "executor.h"
+
+#include "helper.h"
+
+#include "psppire-var-ptr.h"
+
+#include "paired-dialog.h"
+#include "npar-two-sample-related.h"
+
+#include <gettext.h>
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+enum test
+  {
+    NT_WILCOXON,
+    NT_SIGN,
+    NT_MCNEMAR,
+    n_Tests
+  };
+
+struct ts_test
+{
+  GtkWidget *button;
+  char syntax[16];
+};
+
+
+static void
+refresh (void *aux)
+{
+  int i;
+  struct ts_test *tst = aux;
+
+  for (i = 0 ; i < n_Tests; ++i)
+    {
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tst[i].button), FALSE);
+    }
+}
+
+
+static gboolean
+valid (void *aux)
+{
+  int i;
+  struct ts_test *tst = aux;
+
+  for (i = 0 ; i < n_Tests; ++i)
+    {
+      if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (tst[i].button)))
+       return TRUE;
+    }
+
+  return FALSE;
+}
+
+
+
+static gchar *
+generate_syntax (struct paired_samples_dialog *psd, const struct ts_test *test)
+{
+  int i;
+  gchar *text = NULL;
+  GString *str = g_string_new ("NPAR TEST");
+
+  for (i = 0 ; i < n_Tests; ++i)
+  {
+    if (! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (test[i].button)))
+      continue;
+
+    g_string_append (str, "\n\t");
+    g_string_append (str, test[i].syntax);
+
+    psppire_var_view_append_names (PSPPIRE_VAR_VIEW (psd->pairs_treeview), 0, str);
+
+    g_string_append (str, " WITH ");
+
+    psppire_var_view_append_names (PSPPIRE_VAR_VIEW (psd->pairs_treeview), 1, str);
+
+    g_string_append (str, " (PAIRED)");
+  }
+
+  g_string_append (str, ".\n");
+
+  text = str->str;
+  g_string_free (str, FALSE);
+
+  return text;
+}
+
+/* Pops up the dialog box */
+void
+two_related_dialog (PsppireDataWindow *de)
+{
+  gint response;
+  struct ts_test nts[n_Tests];
+  struct paired_samples_dialog *tt_d = two_sample_dialog_create (de);
+
+  GtkWidget *frame = gtk_frame_new (_("Test Type"));
+  GtkWidget *bb = gtk_vbutton_box_new ();
+
+  strcpy (nts[NT_WILCOXON].syntax, "/WILCOXON");
+  strcpy (nts[NT_SIGN].syntax, "/SIGN");
+  strcpy (nts[NT_MCNEMAR].syntax, "/MCNEMAR");
+
+  nts[NT_WILCOXON].button = gtk_check_button_new_with_mnemonic (_("_Wilcoxon"));
+  nts[NT_SIGN].button = gtk_check_button_new_with_mnemonic (_("_Sign"));
+  nts[NT_MCNEMAR].button = gtk_check_button_new_with_mnemonic (_("_McNemar"));
+
+  gtk_box_pack_start (GTK_BOX (bb), nts[NT_WILCOXON].button, FALSE, FALSE, 5);
+  gtk_box_pack_start (GTK_BOX (bb), nts[NT_SIGN].button,     FALSE, FALSE, 5);
+  gtk_box_pack_start (GTK_BOX (bb), nts[NT_MCNEMAR].button,  FALSE, FALSE, 5);
+
+  gtk_container_add (GTK_CONTAINER (frame), bb);
+
+  gtk_widget_show_all (frame);
+  two_sample_dialog_add_widget (tt_d, frame);
+
+  tt_d->refresh = refresh;
+  tt_d->valid = valid;
+  tt_d->aux = nts;
+
+  gtk_window_set_title (GTK_WINDOW (tt_d->dialog), _("Two-Related-Samples Tests"));
+
+  response = psppire_dialog_run (PSPPIRE_DIALOG (tt_d->dialog));
+
+  switch (response)
+    {
+    case GTK_RESPONSE_OK:
+      g_free (execute_syntax_string (de, generate_syntax (tt_d, nts)));
+      break;
+    case PSPPIRE_RESPONSE_PASTE:
+      g_free (paste_syntax_to_window (generate_syntax (tt_d, nts)));
+      break;
+    default:
+      break;
+    }
+
+  two_sample_dialog_destroy (tt_d);
+}
diff --git a/src/ui/gui/npar-two-sample-related.h b/src/ui/gui/npar-two-sample-related.h
new file mode 100644 (file)
index 0000000..de3a860
--- /dev/null
@@ -0,0 +1,26 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  Free Software Foundation
+
+   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/>.
+*/
+
+#ifndef NPAR_PAIRED_H
+#define NPAR_PAIRED_H 1
+
+#include "psppire-data-window.h"
+
+/* Pops up the dialog box */
+void two_related_dialog (PsppireDataWindow *de);
+
+#endif
index 16334ef248f34a60565f387fce29326fcfa4edd4..de4e8b3be466318a6f67fb9d15341c244972c681 100644 (file)
         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
         <property name="spacing">2</property>
         <child>
-          <object class="GtkTable" id="table4">
+          <object class="GtkAlignment" id="alignment2">
             <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="n_rows">3</property>
-            <property name="n_columns">3</property>
+            <property name="top_padding">5</property>
+            <property name="bottom_padding">5</property>
+            <property name="left_padding">5</property>
             <child>
-              <object class="GtkVBox" id="vbox30">
+              <object class="GtkTable" id="table4">
                 <property name="visible">True</property>
                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="orientation">vertical</property>
+                <property name="n_rows">3</property>
+                <property name="n_columns">3</property>
                 <child>
-                  <object class="GtkLabel" id="label36">
+                  <object class="GtkVBox" id="vbox30">
                     <property name="visible">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">_Factor:</property>
-                    <property name="use_underline">True</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <object class="GtkLabel" id="label36">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">_Factor:</property>
+                        <property name="use_underline">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkEntry" id="oneway-anova-entry">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="invisible_char">&#x25CF;</property>
+                      </object>
+                      <packing>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
                   </object>
                   <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">0</property>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="y_options"></property>
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkEntry" id="oneway-anova-entry">
+                  <object class="GtkVBox" id="vbox29">
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <object class="GtkLabel" id="label35">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Dependent _Variable(s):</property>
+                        <property name="use_underline">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkScrolledWindow" id="scrolledwindow15">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="hscrollbar_policy">automatic</property>
+                        <property name="vscrollbar_policy">automatic</property>
+                        <property name="shadow_type">etched-in</property>
+                        <child>
+                          <object class="PsppireVarView" id="oneway-anova-treeview2">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="headers_visible">False</property>
+                            <property name="headers_clickable">False</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="PsppireSelector" id="oneway-anova-selector2">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="border_width">5</property>
+                    <property name="source_widget">oneway-anova-treeview1</property>
+                    <property name="dest_widget">oneway-anova-entry</property>
                   </object>
                   <packing>
-                    <property name="position">1</property>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="x_options"></property>
+                    <property name="y_options"></property>
                   </packing>
                 </child>
-              </object>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkVBox" id="vbox29">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="orientation">vertical</property>
                 <child>
-                  <object class="GtkLabel" id="label35">
+                  <object class="PsppireSelector" id="oneway-anova-selector1">
                     <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Dependent _Variable(s):</property>
-                    <property name="use_underline">True</property>
+                    <property name="border_width">5</property>
+                    <property name="source_widget">oneway-anova-treeview1</property>
+                    <property name="dest_widget">oneway-anova-treeview2</property>
                   </object>
                   <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">0</property>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="x_options"></property>
+                    <property name="y_options">GTK_EXPAND</property>
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkScrolledWindow" id="scrolledwindow15">
+                  <object class="GtkScrolledWindow" id="scrolledwindow2">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="hscrollbar_policy">automatic</property>
+                    <property name="hscrollbar_policy">never</property>
                     <property name="vscrollbar_policy">automatic</property>
                     <property name="shadow_type">etched-in</property>
                     <child>
-                      <object class="PsppireVarView" id="oneway-anova-treeview2">
+                      <object class="PsppireDictView" id="oneway-anova-treeview1">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                         <property name="headers_visible">False</property>
+                        <property name="headers_clickable">False</property>
                       </object>
                     </child>
                   </object>
                   <packing>
-                    <property name="position">1</property>
+                    <property name="bottom_attach">3</property>
                   </packing>
                 </child>
-              </object>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-              </packing>
-            </child>
-            <child>
-              <object class="PsppireSelector" id="oneway-anova-selector2">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="border_width">5</property>
-                <property name="source_widget">oneway-anova-treeview1</property>
-                <property name="dest_widget">oneway-anova-entry</property>
-              </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-                <property name="x_options"></property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <object class="PsppireSelector" id="oneway-anova-selector1">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="border_width">5</property>
-                <property name="primary">True</property>
-                <property name="source_widget">oneway-anova-treeview1</property>
-                <property name="dest_widget">oneway-anova-treeview2</property>
-              </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="x_options"></property>
-                <property name="y_options">GTK_EXPAND</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkScrolledWindow" id="scrolledwindow2">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="hscrollbar_policy">never</property>
-                <property name="vscrollbar_policy">automatic</property>
-                <property name="shadow_type">etched-in</property>
-                <child>
-                  <object class="PsppireDictView" id="oneway-anova-treeview1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="headers_visible">False</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="bottom_attach">3</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkHBox" id="hbox2">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="spacing">5</property>
                 <child>
-                  <object class="GtkFrame" id="frame2">
+                  <object class="GtkHBox" id="hbox2">
                     <property name="visible">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label_xalign">0</property>
+                    <property name="spacing">5</property>
                     <child>
-                      <object class="GtkAlignment" id="alignment2">
+                      <object class="GtkFrame" id="frame2">
                         <property name="visible">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="left_padding">12</property>
+                        <property name="label_xalign">0</property>
                         <child>
-                          <object class="GtkVButtonBox" id="vbuttonbox1">
+                          <object class="GtkAlignment" id="alignment3">
                             <property name="visible">True</property>
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="left_padding">12</property>
                             <child>
-                              <object class="GtkCheckButton" id="checkbutton1">
-                                <property name="label" translatable="yes">_Descriptives</property>
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="receives_default">False</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="use_underline">True</property>
-                                <property name="draw_indicator">True</property>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkCheckButton" id="checkbutton2">
-                                <property name="label" translatable="yes">_Homogeneity</property>
+                              <object class="GtkVButtonBox" id="vbuttonbox1">
                                 <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="receives_default">False</property>
                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="use_underline">True</property>
-                                <property name="draw_indicator">True</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkCheckButton" id="checkbutton1">
+                                    <property name="label" translatable="yes">_Descriptives</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">False</property>
+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="draw_indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="checkbutton2">
+                                    <property name="label" translatable="yes">_Homogeneity</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">False</property>
+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="draw_indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
                               </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                                <property name="position">1</property>
-                              </packing>
                             </child>
                           </object>
                         </child>
+                        <child type="label">
+                          <object class="GtkLabel" id="label1">
+                            <property name="visible">True</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="label" translatable="yes">Statistics</property>
+                            <property name="use_markup">True</property>
+                          </object>
+                        </child>
                       </object>
+                      <packing>
+                        <property name="position">0</property>
+                      </packing>
                     </child>
-                    <child type="label">
-                      <object class="GtkLabel" id="label1">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="label" translatable="yes">Statistics</property>
-                        <property name="use_markup">True</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkVButtonBox" id="vbuttonbox2">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="orientation">vertical</property>
                     <child>
-                      <object class="GtkButton" id="contrasts-button">
-                        <property name="label" translatable="yes">_Contrasts...</property>
+                      <object class="GtkVButtonBox" id="vbuttonbox2">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="use_underline">True</property>
+                        <property name="orientation">vertical</property>
+                        <child>
+                          <object class="GtkButton" id="contrasts-button">
+                            <property name="label" translatable="yes">_Contrasts...</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
                       </object>
                       <packing>
                         <property name="expand">False</property>
                         <property name="fill">False</property>
-                        <property name="position">0</property>
+                        <property name="position">1</property>
                       </packing>
                     </child>
                   </object>
                   <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                    <property name="y_options"></property>
+                    <property name="x_padding">5</property>
+                    <property name="y_padding">5</property>
                   </packing>
                 </child>
               </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">3</property>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
-                <property name="y_options"></property>
-                <property name="x_padding">5</property>
-                <property name="y_padding">5</property>
-              </packing>
             </child>
           </object>
           <packing>
                             <property name="xalign">1</property>
                             <property name="label" translatable="yes">_Coefficients:</property>
                             <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">entry1</property>
                           </object>
                           <packing>
                             <property name="expand">False</property>
diff --git a/src/ui/gui/paired-dialog.c b/src/ui/gui/paired-dialog.c
new file mode 100644 (file)
index 0000000..39a8ae9
--- /dev/null
@@ -0,0 +1,187 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  Free Software Foundation
+
+   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 <gtk/gtk.h>
+
+
+#include "paired-dialog.h"
+
+#include "psppire-data-window.h"
+#include "psppire-selector.h"
+#include "psppire-var-view.h"
+
+#include "psppire-dict.h"
+#include "psppire-var-store.h"
+
+#include "dialog-common.h"
+#include "psppire-dialog.h"
+
+#include "psppire-var-ptr.h"
+
+
+#include "helper.h"
+
+
+
+static void
+refresh (struct paired_samples_dialog *tt_d)
+{
+  gtk_list_store_clear (GTK_LIST_STORE (tt_d->list_store));
+
+  if (tt_d->refresh)
+    tt_d->refresh (tt_d->aux);
+}
+
+static gboolean
+dialog_state_valid (gpointer data)
+{
+  struct variable *v = NULL;
+  struct paired_samples_dialog *tt_d = data;
+  GtkTreeIter dest_iter;
+
+  gint n_rows = gtk_tree_model_iter_n_children  (tt_d->list_store, NULL);
+
+  if ( n_rows == 0 )
+    return FALSE;
+
+  /* Get the last row */
+  gtk_tree_model_iter_nth_child (tt_d->list_store, &dest_iter,
+                                NULL, n_rows - 1);
+
+  /* Get the last (2nd) column */
+  gtk_tree_model_get (tt_d->list_store, &dest_iter, 1, &v, -1);
+
+
+  if (v == NULL)
+    return FALSE;
+    
+  if ( NULL == tt_d->valid)
+    return TRUE;
+
+  return tt_d->valid (tt_d->aux);
+}
+
+
+
+static void
+select_as_pair_member (GtkTreeIter source_iter,
+                      GtkWidget *dest,
+                      GtkTreeModel *source_model,
+                      gpointer data)
+{
+  struct variable *v;
+  struct variable *v1;
+  gint n_rows;
+  GtkTreeIter dest_iter;
+  struct paired_samples_dialog *tt_d = data;
+
+
+  gtk_tree_model_get (source_model, &source_iter,
+                     DICT_TVM_COL_VAR, &v, -1);
+
+  n_rows = gtk_tree_model_iter_n_children  (tt_d->list_store, NULL);
+
+  if ( n_rows > 0 )
+    {
+
+      gtk_tree_model_iter_nth_child (tt_d->list_store,
+                                    &dest_iter, NULL, n_rows - 1);
+
+      gtk_tree_model_get (tt_d->list_store, &dest_iter, 1, &v1, -1);
+    }
+  else
+    v1 = NULL;
+
+  if ( n_rows == 0 || v1 != NULL)
+    {
+      gtk_list_store_append (GTK_LIST_STORE (tt_d->list_store), &dest_iter);
+
+      gtk_list_store_set (GTK_LIST_STORE (tt_d->list_store), &dest_iter,
+                         0, v,
+                         1, NULL,
+                         -1);
+    }
+  else
+    {
+      gtk_list_store_set (GTK_LIST_STORE (tt_d->list_store), &dest_iter,
+                         1, v,
+                         -1);
+
+    }
+}
+
+void
+two_sample_dialog_add_widget (struct paired_samples_dialog *psd, GtkWidget *w)
+{
+  GtkWidget *box = get_widget_assert (psd->xml, "vbox3");
+  gtk_box_pack_start (GTK_BOX (box), w, FALSE, FALSE,  5);
+}
+
+void
+two_sample_dialog_destroy (struct paired_samples_dialog *psd)
+{
+  g_object_unref (psd->xml);
+  free (psd);
+}
+
+struct paired_samples_dialog *
+two_sample_dialog_create (PsppireDataWindow *de)
+{
+  GtkWidget *dict_view ;
+  GtkWidget *selector ;
+  struct paired_samples_dialog *tt_d = g_malloc (sizeof *tt_d);
+
+  PsppireVarStore *vs = NULL;
+
+  tt_d->xml = builder_new ("paired-samples.ui");
+
+  dict_view = get_widget_assert (tt_d->xml, "paired-samples-t-test-treeview1");
+
+  selector = get_widget_assert (tt_d->xml, "psppire-selector3");
+
+  tt_d->dialog = get_widget_assert (tt_d->xml, "t-test-paired-samples-dialog");
+
+  g_object_get (de->data_editor, "var-store", &vs, NULL);
+
+  g_object_get (vs, "dictionary", &tt_d->dict, NULL);
+  tt_d->pairs_treeview =
+   get_widget_assert (tt_d->xml, "paired-samples-t-test-treeview2");
+
+  gtk_window_set_transient_for (GTK_WINDOW (tt_d->dialog), GTK_WINDOW (de));
+
+
+  g_object_set (dict_view, "model", tt_d->dict,
+               "predicate",
+               var_is_numeric, NULL);
+
+  
+  tt_d->list_store = gtk_tree_view_get_model (GTK_TREE_VIEW (tt_d->pairs_treeview));
+
+  psppire_selector_set_select_func (PSPPIRE_SELECTOR (selector),
+                                   select_as_pair_member,
+                                   tt_d);
+
+  g_signal_connect_swapped (tt_d->dialog, "refresh",
+                           G_CALLBACK (refresh),  tt_d);
+
+  psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (tt_d->dialog),
+                                     dialog_state_valid, tt_d);
+
+  return tt_d;
+}
diff --git a/src/ui/gui/paired-dialog.h b/src/ui/gui/paired-dialog.h
new file mode 100644 (file)
index 0000000..c370f77
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef PAIRED_DIALOG_H
+#define PAIRED_DIALOG_H 1
+
+#include  "psppire-data-window.h"
+#include  "psppire-dict.h"
+
+#include <gtk/gtk.h>
+
+typedef void refresh_f (void *aux);
+typedef gboolean valid_f (void *aux);
+
+struct paired_samples_dialog
+{
+  PsppireDict *dict;
+  GtkWidget *pairs_treeview;
+  GtkTreeModel *list_store;
+  GtkWidget *dialog;
+  GtkBuilder *xml;
+
+  refresh_f *refresh;
+  valid_f *valid;
+  void *aux;
+};
+
+
+struct paired_samples_dialog *two_sample_dialog_create (PsppireDataWindow *de);
+void two_sample_dialog_destroy (struct paired_samples_dialog *psd);
+void two_sample_dialog_add_widget (struct paired_samples_dialog *psd, GtkWidget *w);
+
+
+#endif
diff --git a/src/ui/gui/paired-samples.ui b/src/ui/gui/paired-samples.ui
new file mode 100644 (file)
index 0000000..6c9c71e
--- /dev/null
@@ -0,0 +1,156 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="psppire" version="2054.17080"/>
+  <!-- interface-requires gtk+ 2.12 -->
+  <!-- interface-naming-policy project-wide -->
+  <object class="PsppireDialog" id="t-test-paired-samples-dialog">
+    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+    <property name="modal">True</property>
+    <child internal-child="hbox">
+      <object class="GtkHBox" id="dialog-hbox6">
+        <property name="visible">True</property>
+        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+        <property name="spacing">2</property>
+        <child>
+          <object class="GtkAlignment" id="alignment1">
+            <property name="visible">True</property>
+            <property name="top_padding">5</property>
+            <property name="bottom_padding">5</property>
+            <property name="left_padding">5</property>
+            <child>
+              <object class="GtkHBox" id="hbox3">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <child>
+                  <object class="GtkScrolledWindow" id="scrolledwindow2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="hscrollbar_policy">never</property>
+                    <property name="vscrollbar_policy">automatic</property>
+                    <property name="shadow_type">etched-in</property>
+                    <child>
+                      <object class="PsppireDictView" id="paired-samples-t-test-treeview1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="headers_visible">False</property>
+                        <property name="headers_clickable">False</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkAlignment" id="alignment5">
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="yalign">0.059999998658895493</property>
+                    <property name="yscale">0</property>
+                    <child>
+                      <object class="PsppireSelector" id="psppire-selector3">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="no_show_all">True</property>
+                        <property name="border_width">5</property>
+                        <property name="source_widget">paired-samples-t-test-treeview1</property>
+                        <property name="dest_widget">paired-samples-t-test-treeview2</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkVBox" id="vbox3">
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="orientation">vertical</property>
+                    <property name="spacing">5</property>
+                    <child>
+                      <object class="GtkFrame" id="frame4">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="label_xalign">0</property>
+                        <property name="shadow_type">none</property>
+                        <child>
+                          <object class="GtkAlignment" id="alignment6">
+                            <property name="visible">True</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="left_padding">12</property>
+                            <child>
+                              <object class="GtkScrolledWindow" id="scrolledwindow1">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="vscrollbar_policy">automatic</property>
+                                <property name="shadow_type">etched-in</property>
+                                <child>
+                                  <object class="PsppireVarView" id="paired-samples-t-test-treeview2">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                    <property name="headers_clickable">False</property>
+                                    <property name="enable_search">False</property>
+                                    <property name="n_cols">2</property>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                        <child type="label">
+                          <object class="GtkLabel" id="label13">
+                            <property name="visible">True</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="label" translatable="yes">Test _Pair(s):</property>
+                            <property name="use_markup">True</property>
+                            <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">paired-samples-t-test-treeview2</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="PsppireVButtonBox" id="psppire-vbuttonbox4">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="border_width">5</property>
+            <property name="orientation">vertical</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
index be4702d34349ee65a1e4ca47726dc08c262a1c34..49438d6cff14f5af7a68150455de8a741aa13410 100644 (file)
 #include "libpspp/message.h"
 #include "libpspp/str.h"
 #include "ui/gui/aggregate-dialog.h"
+#include "ui/gui/autorecode-dialog.h"
 #include "ui/gui/binomial-dialog.h"
 #include "ui/gui/chi-square-dialog.h"
 #include "ui/gui/comments-dialog.h"
 #include "ui/gui/compute-dialog.h"
 #include "ui/gui/correlation-dialog.h"
+#include "ui/gui/count-dialog.h"
 #include "ui/gui/crosstabs-dialog.h"
 #include "ui/gui/descriptives-dialog.h"
 #include "ui/gui/entry-dialog.h"
 #include "ui/gui/goto-case-dialog.h"
 #include "ui/gui/help-menu.h"
 #include "ui/gui/helper.h"
+#include "ui/gui/k-means-dialog.h"
 #include "ui/gui/k-related-dialog.h"
+#include "ui/gui/npar-two-sample-related.h"
 #include "ui/gui/oneway-anova-dialog.h"
 #include "ui/gui/psppire-data-window.h"
 #include "ui/gui/psppire-syntax-window.h"
 #include "ui/gui/psppire-window.h"
 #include "ui/gui/psppire.h"
 #include "ui/gui/rank-dialog.h"
+#include "ui/gui/runs-dialog.h"
+#include "ui/gui/ks-one-sample-dialog.h"
 #include "ui/gui/recode-dialog.h"
 #include "ui/gui/regression-dialog.h"
 #include "ui/gui/reliability-dialog.h"
@@ -385,7 +391,8 @@ load_file (PsppireWindow *de, const gchar *file_name)
   mime_type = (name_has_por_suffix (file_name)
                ? "application/x-spss-por"
                : "application/x-spss-sav");
-  add_most_recent (ds_cstr (&filename), mime_type);
+
+  add_most_recent (file_name, mime_type);
 
   return ok;
 }
@@ -486,6 +493,7 @@ static void
 data_pick_filename (PsppireWindow *window)
 {
   PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (window);
+  GtkFileFilter *filter = gtk_file_filter_new ();
   GtkWidget *button_sys;
   GtkWidget *dialog =
     gtk_file_chooser_dialog_new (_("Save"),
@@ -495,7 +503,8 @@ data_pick_filename (PsppireWindow *window)
                                 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
                                 NULL);
 
-  GtkFileFilter *filter = gtk_file_filter_new ();
+  g_object_set (dialog, "local-only", FALSE, NULL);
+
   gtk_file_filter_set_name (filter, _("System Files (*.sav)"));
   gtk_file_filter_add_pattern (filter, "*.sav");
   gtk_file_filter_add_pattern (filter, "*.SAV");
@@ -1066,6 +1075,8 @@ psppire_data_window_finish_init (PsppireDataWindow *de,
 
   connect_action (de, "transform_compute", G_CALLBACK (compute_dialog));
 
+  connect_action (de, "transform_autorecode", G_CALLBACK (autorecode_dialog));
+
   connect_action (de, "edit_find", G_CALLBACK (find_dialog));
 
   connect_action (de, "data_split-file", G_CALLBACK (split_file_dialog));
@@ -1086,6 +1097,8 @@ psppire_data_window_finish_init (PsppireDataWindow *de,
   connect_action (de, "utilities_comments", G_CALLBACK (comments_dialog));
  
   connect_action (de, "transform_rank", G_CALLBACK (rank_dialog));
+
+  connect_action (de, "transform_count", G_CALLBACK (count_dialog));
  
   connect_action (de, "transform_recode-same", G_CALLBACK (recode_same_dialog));
  
@@ -1109,11 +1122,14 @@ psppire_data_window_finish_init (PsppireDataWindow *de,
  
   connect_action (de, "factor-analysis", G_CALLBACK (factor_dialog));
 
-  connect_action (de, "chi-square", G_CALLBACK (chisquare_dialog));
+  connect_action (de, "k-means", G_CALLBACK (k_means_dialog));
 
+  connect_action (de, "chi-square", G_CALLBACK (chisquare_dialog));
   connect_action (de, "binomial", G_CALLBACK (binomial_dialog));
-
+  connect_action (de, "runs", G_CALLBACK (runs_dialog));
+  connect_action (de, "ks-one-sample", G_CALLBACK (ks_one_sample_dialog));
   connect_action (de, "k-related-samples", G_CALLBACK (k_related_dialog));
+  connect_action (de, "two-related-samples", G_CALLBACK (two_related_dialog));
  
 
   {
@@ -1132,13 +1148,14 @@ psppire_data_window_finish_init (PsppireDataWindow *de,
     GtkWidget *menu_files = gtk_recent_chooser_menu_new_for_manager (
       gtk_recent_manager_get_default ());
 
+    g_object_set (menu_data, "show-tips",  TRUE, NULL);
+    g_object_set (menu_files, "show-tips",  TRUE, NULL);
+
     {
       GtkRecentFilter *filter = gtk_recent_filter_new ();
 
-      gtk_recent_filter_add_pattern (filter, "*.sav");
-      gtk_recent_filter_add_pattern (filter, "*.SAV");
-      gtk_recent_filter_add_pattern (filter, "*.por");
-      gtk_recent_filter_add_pattern (filter, "*.POR");
+      gtk_recent_filter_add_mime_type (filter, "application/x-spss-sav");
+      gtk_recent_filter_add_mime_type (filter, "application/x-spss-por");
 
       gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_data), GTK_RECENT_SORT_MRU);
 
index e7e0ad042daa1763ce2ff0c5b29242fcad56727d..6f27aa54d13e41883c1adb0037acd7c8e6224383 100644 (file)
@@ -23,6 +23,7 @@
 #include "psppire-selector.h"
 #include "psppire-conf.h"
 #include <string.h>
+#include "helper.h"
 
 static void psppire_dialog_class_init          (PsppireDialogClass *);
 static void psppire_dialog_init                (PsppireDialog      *);
index 6f7865eb770afd775187a6cef0e4f10de5a0292c..d4eeff6119a177926a19a38cc79355e09297c462 100644 (file)
@@ -206,9 +206,6 @@ enter_leave_notify (GtkWidget   *widget,
  if (event->type == GDK_ENTER_NOTIFY)
    gtk_widget_grab_focus (widget);
 
- if (event->type == GDK_LEAVE_NOTIFY)
-   GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
-
  return FALSE;
 }
 
@@ -313,8 +310,7 @@ psppire_keypad_init (PsppireKeypad *kp)
   const int digit_voffset = 0;
   const int digit_hoffset = 3;
 
-  GTK_WIDGET_SET_FLAGS (kp, GTK_CAN_FOCUS);
-  GTK_WIDGET_UNSET_FLAGS (kp, GTK_HAS_FOCUS);
+  gtk_widget_set_can_focus (GTK_WIDGET (kp), TRUE);
 
   kp->dispose_has_run = FALSE;
 
index 553dbf7e596bbc8b91b219420d65fd7dd099b556..0e6fa8e5b90aa5f7e68653a26cce5df7881e76bb 100644 (file)
@@ -102,7 +102,7 @@ struct _PsppireKeypad
 
 struct _PsppireKeypadClass
 {
-  GtkTableClass parent_class;
+  GtkEventBoxClass parent_class;
   void (*keypad)(PsppireKeypad*);
 };
 
index cf65a2f9e6c518c7dbd7b6581a0808b10ea06c92..a29fcc6cd5bc23e8f1fe28ad1084ea34e30b226a 100644 (file)
@@ -586,6 +586,8 @@ psppire_output_window_export (PsppireOutputWindow *window)
                                         GTK_STOCK_SAVE,   GTK_RESPONSE_ACCEPT,
                                         NULL);
 
+  g_object_set (dialog, "local-only", FALSE, NULL);
+
   chooser = GTK_FILE_CHOOSER (dialog);
 
   list = create_file_type_list ();
diff --git a/src/ui/gui/psppire-scanf.c b/src/ui/gui/psppire-scanf.c
new file mode 100644 (file)
index 0000000..2396245
--- /dev/null
@@ -0,0 +1,387 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011 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 <gtk/gtk.h>
+#include "psppire-scanf.h"
+
+#include <gl/printf-parse.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include "xalloc.h"
+
+
+static void psppire_scanf_class_init          (PsppireScanfClass *class);
+static void psppire_scanf_init                (PsppireScanf      *w);
+
+G_DEFINE_TYPE (PsppireScanf, psppire_scanf, GTK_TYPE_HBOX)
+
+/* Properties */
+enum
+{
+  PROP_0,
+  PROP_FORMAT,
+  PROP_NCONV,
+  PROP_USE_UNDERLINE,
+  PROP_MNEMONIC_WIDGET
+};
+
+/* Create a GtkLabel and pack it into BOX.
+   The label is created using part of the string at S, and the directives
+   at DIRS[DIR_IDX] and subsequent.
+
+   After this function returns, *S points to the first unused character.
+*/
+static void
+ship_label (PsppireScanf *box, const char **s,
+           const char_directives *dirs, size_t dir_idx)
+{
+  GtkWidget *label ;
+  GString *str = g_string_new (*s);
+
+  if ( dirs)
+    {
+      char_directive dir = dirs->dir[dir_idx];
+      int n = 0;
+
+      while (dir_idx < dirs->count && dir.conversion == '%' )
+       {
+         g_string_erase (str, dir.dir_start - *s, 1);
+         dir = dirs->dir[++dir_idx];
+         n++;
+       }
+
+      g_string_truncate (str, dir.dir_start - *s - n);
+
+      if ( dir_idx >= dirs->count)
+       *s = NULL;
+      else
+       *s = dir.dir_end;
+    }
+
+  label = gtk_label_new (str->str);
+
+  g_string_free (str, TRUE);
+
+  gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+  gtk_widget_show (label);
+}
+
+static void
+guts (PsppireScanf *scanf)
+{
+  gint i;
+  arguments a;
+  const char *s = scanf->format;
+
+  /* Get the number of args into D */
+  g_return_if_fail (0 == printf_parse (scanf->format, &scanf->d, &a));
+
+  if ( scanf->d.count > 0)
+    scanf->widgets = xcalloc (sizeof (*scanf->widgets), scanf->d.count);
+
+  /* A is not used, so get rid of it */
+  if (a.arg != a.direct_alloc_arg)
+    free (a.arg);
+
+  for (i = 0 ; i < scanf->d.count ; ++i )
+    {
+      GtkWidget **w;
+      char_directive dir = scanf->d.dir[i];
+      int precision = 0;
+      int width = 0;
+
+      if ( dir.precision_start && dir.precision_end)
+       precision = strtol (dir.precision_start + 1,
+                           (char **) &dir.precision_end, 10);
+
+      if ( dir.width_start && dir.width_end )
+       width = strtol (dir.width_start, (char **) &dir.width_end, 10);
+
+      if ( dir.dir_start > s )
+       ship_label (scanf, &s, &scanf->d, i);
+
+      if ( dir.conversion == '%')
+       {
+         if (s) s++;
+         continue;
+       }
+
+      w = &scanf->widgets [dir.arg_index];
+      switch (dir.conversion)
+       {
+       case 'd':
+       case 'i':
+       case 'f':
+         {
+           *w = gtk_spin_button_new_with_range (0, 100.0, 1.0);
+           g_object_set (*w, "digits", precision, NULL);
+         }
+         break;
+       case 's':
+         *w = gtk_entry_new ();
+         break;
+       };
+      g_object_set (*w, "width-chars", width, NULL);
+      gtk_box_pack_start (GTK_BOX (scanf), *w, FALSE, FALSE, 0);
+      gtk_widget_show (*w);
+    }
+
+  if ( s && *s )
+    ship_label (scanf, &s, NULL, 0);
+
+}
+
+
+static void
+set_mnemonic (PsppireScanf *scanf)
+{
+  if (scanf->use_underline || scanf->mnemonic_widget)
+    {
+      GList *l = gtk_container_get_children (GTK_CONTAINER (scanf));
+      while (l)
+       {
+         if ( GTK_IS_LABEL (l->data))
+           {
+             const gchar *t = gtk_label_get_label (l->data);
+             if  ( g_strstr_len (t, -1,  "_"))
+               {
+                 g_object_set (l->data,
+                               "use-underline", TRUE,
+                               "mnemonic-widget", scanf->mnemonic_widget,
+                               NULL);
+
+                 break;
+               }
+           }
+         l = l->next;
+       }
+      g_list_free (l);
+    }
+}
+
+static void
+psppire_scanf_set_property (GObject         *object,
+                           guint            prop_id,
+                           const GValue    *value,
+                           GParamSpec      *pspec)
+{
+  PsppireScanf *scanf = PSPPIRE_SCANF (object);
+
+  switch (prop_id)
+    {
+    case PROP_FORMAT:
+      scanf->format = g_value_get_string (value);
+      guts (scanf);
+      break;
+    case PROP_MNEMONIC_WIDGET:
+      scanf->mnemonic_widget = g_value_get_object (value);
+      set_mnemonic (scanf);
+      break;
+    case PROP_USE_UNDERLINE:
+      scanf->use_underline = g_value_get_boolean (value);
+      set_mnemonic (scanf);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    };
+}
+
+
+static void
+psppire_scanf_get_property (GObject         *object,
+                           guint            prop_id,
+                           GValue          *value,
+                           GParamSpec      *pspec)
+{
+  PsppireScanf *scanf = PSPPIRE_SCANF (object);
+
+  switch (prop_id)
+    {
+    case PROP_FORMAT:
+      g_value_set_string (value, scanf->format);
+      break;
+    case PROP_NCONV:
+      g_value_set_int (value, scanf->d.count);
+      break;
+    case PROP_USE_UNDERLINE:
+      g_value_set_boolean (value, scanf->use_underline);
+      break;
+    case PROP_MNEMONIC_WIDGET:
+      g_value_set_object (value, scanf->mnemonic_widget);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    };
+}
+
+
+static GObjectClass *parent_class = NULL;
+
+static void
+psppire_scanf_dispose (GObject *obj)
+{
+  PsppireScanf *w = (PsppireScanf *)obj;
+
+  if (w->dispose_has_run)
+    return;
+
+  /* Make sure dispose does not run twice. */
+  w->dispose_has_run = TRUE;
+
+
+  /* Chain up to the parent class */
+  G_OBJECT_CLASS (parent_class)->dispose (obj);
+}
+
+static void
+psppire_scanf_finalize (GObject *obj)
+{
+  PsppireScanf *w = PSPPIRE_SCANF (obj);
+
+  free (w->widgets);
+
+  if (w->d.dir != w->d.direct_alloc_dir)
+    free (w->d.dir);
+
+   /* Chain up to the parent class */
+   G_OBJECT_CLASS (parent_class)->finalize (obj);
+}
+
+static void
+psppire_scanf_class_init (PsppireScanfClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  GParamSpec *format_spec =
+    g_param_spec_string ("format",
+                      "Format",
+                      "A Scanf style format string",
+                      NULL,
+                      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+
+  GParamSpec *nconv_spec =
+    g_param_spec_int ("n-conv",
+                      "Conversions",
+                      "The number of conversions in the format string",
+                     0, G_MAXINT, 0,
+                      G_PARAM_READABLE);
+
+
+  GParamSpec *use_underline_spec =
+    g_param_spec_boolean ("use-underline",
+                      "Use Underline",
+                      "If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key",
+                         FALSE,
+                         G_PARAM_READWRITE);
+
+
+  GParamSpec *mnemonic_widget_spec =
+    g_param_spec_object ("mnemonic-widget",
+                      "Mnemonic widget",
+                      "The widget which is to be activated when the Scanf's mnemonic key is pressed.  Has no effect if use-underline is false.",
+                        GTK_TYPE_WIDGET,
+                        G_PARAM_READWRITE);
+
+
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class->dispose = psppire_scanf_dispose;
+  object_class->finalize = psppire_scanf_finalize;
+
+  object_class->set_property = psppire_scanf_set_property;
+  object_class->get_property = psppire_scanf_get_property;
+
+  g_object_class_install_property (object_class,
+                                   PROP_NCONV,
+                                   nconv_spec);
+
+  g_object_class_install_property (object_class,
+                                   PROP_FORMAT,
+                                   format_spec);
+
+  g_object_class_install_property (object_class,
+                                   PROP_USE_UNDERLINE,
+                                   use_underline_spec);
+
+  g_object_class_install_property (object_class,
+                                   PROP_MNEMONIC_WIDGET,
+                                   mnemonic_widget_spec);
+}
+
+
+
+static void
+psppire_scanf_init (PsppireScanf *w)
+{
+}
+
+gchar
+psppire_get_conversion_char (PsppireScanf *w, gint n)
+{
+  g_return_val_if_fail ( n < w->d.count, '\0');
+  return w->d.dir[n].conversion;
+}
+
+GtkWidget *
+psppire_scanf_get_child (PsppireScanf *w, gint n)
+{
+  g_return_val_if_fail ( n < w->d.count, NULL);
+  return w->widgets[n];
+}
+
+
+/*
+   This widget is a GtkHBox populated with GtkLabel and GtkEntry widgets.
+   Each conversion in FMT will cause a GtkEntry (possibly a GtkSpinButton) to
+   be created.  Any text between conversions produces a GtkLabel.
+   There should be N arguments following FMT should be of type GtkEntry **,
+   where N is the number of conversions.
+   These arguments will be filled with a pointer to the corresponding widgets.
+   Their properties may be changed, but they should not be unrefed.
+ */
+GtkWidget *
+psppire_scanf_new (const gchar *fmt, ...)
+{
+  gint n, i;
+  va_list ap;
+
+  GtkWidget *w = GTK_WIDGET (g_object_new (psppire_scanf_get_type (),
+                                  "format", fmt, NULL));
+
+  g_object_get (w, "n-conv", &n, NULL);
+
+  va_start (ap, fmt);
+
+  for (i = 0 ; i < n ; ++i )
+    {
+      GtkWidget **field;
+
+      if ( psppire_get_conversion_char (PSPPIRE_SCANF (w), i) == '%')
+       continue;
+
+      field = va_arg (ap, GtkWidget **);
+
+      *field = psppire_scanf_get_child (PSPPIRE_SCANF (w), i);
+    }
+  va_end (ap);
+
+  return w;
+}
diff --git a/src/ui/gui/psppire-scanf.h b/src/ui/gui/psppire-scanf.h
new file mode 100644 (file)
index 0000000..a2ef479
--- /dev/null
@@ -0,0 +1,70 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011 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/>. */
+
+
+#ifndef __PSPPIRE_SCANF_H__
+#define __PSPPIRE_SCANF_H__
+
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <gl/printf-parse.h>
+
+
+G_BEGIN_DECLS
+
+#define PSPPIRE_SCANF_TYPE            (psppire_scanf_get_type ())
+#define PSPPIRE_SCANF(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), PSPPIRE_SCANF_TYPE, PsppireScanf))
+#define PSPPIRE_SCANF_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PSPPIRE_SCANF_TYPE, PsppireScanfClass))
+#define PSPPIRE_IS_SCANF(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_SCANF_TYPE))
+#define PSPPIRE_IS_SCANF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPPIRE_SCANF_TYPE))
+
+
+typedef struct _PsppireScanf       PsppireScanf;
+typedef struct _PsppireScanfClass  PsppireScanfClass;
+
+/* All members are private. */
+struct _PsppireScanf
+{
+  GtkHBox parent;
+  const gchar *format;
+
+  GtkWidget **widgets;
+  char_directives d;
+
+  gboolean use_underline;
+  GtkWidget *mnemonic_widget;
+
+  gboolean dispose_has_run;
+};
+
+
+struct _PsppireScanfClass
+{
+  GtkHBoxClass parent_class;
+};
+
+
+GType          psppire_scanf_get_type        (void);
+GtkWidget*     psppire_scanf_new             (const gchar *fmt, ...);
+GtkWidget *    psppire_scanf_get_child (PsppireScanf *w, gint n);
+
+
+G_END_DECLS
+
+#endif /* __PSPPIRE_SCANF_H__ */
index 135bac9958191065ea5c48bc3aa2cd1d8f7b26c9..7b30106013b21297cd9085a9008856b02de04511 100644 (file)
@@ -151,7 +151,7 @@ enum
 };
 
 
-static void on_activate (PsppireSelector *selector, gpointer data);
+static void on_click (GtkButton *b);
 
 static void update_subjects (PsppireSelector *selector);
 
@@ -218,6 +218,7 @@ static void
 psppire_selector_class_init (PsppireSelectorClass *class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GtkButtonClass *button_class = GTK_BUTTON_CLASS (class);
   GParamSpec *orientation_spec =
     g_param_spec_enum ("orientation",
                       "Orientation",
@@ -250,6 +251,8 @@ psppire_selector_class_init (PsppireSelectorClass *class)
                         G_PARAM_READWRITE);
 
 
+  button_class->clicked = on_click;
+
   object_class->set_property = psppire_selector_set_property;
   object_class->get_property = psppire_selector_get_property;
 
@@ -323,9 +326,7 @@ on_row_activate (GtkTreeView       *tree_view,
                 GtkTreeViewColumn *column,
                 gpointer           data)
 {
-  PsppireSelector *selector  = data;
-
-  gtk_action_activate (selector->action);
+  on_click (GTK_BUTTON (data));
 }
 
 /* Callback for when the source selection changes */
@@ -338,12 +339,12 @@ on_source_select (GtkTreeSelection *treeselection, gpointer data)
 
   if ( selector->allow_selection )
     {
-      gtk_action_set_sensitive (selector->action,
+      gtk_widget_set_sensitive (GTK_WIDGET (selector),
                                selector->allow_selection (selector->source, selector->dest));
     }
   else if ( GTK_IS_ENTRY (selector->dest) )
     {
-      gtk_action_set_sensitive (selector->action,
+      gtk_widget_set_sensitive (GTK_WIDGET (selector),
                                gtk_tree_selection_count_selected_rows
                                (treeselection) <= 1 );
     }
@@ -392,16 +393,11 @@ psppire_selector_init (PsppireSelector *selector)
   selector->arrow = gtk_arrow_new (GTK_ARROW_LEFT, GTK_SHADOW_NONE);
   selector->filtered_source = NULL;
 
-  selector->action = gtk_action_new ("select", NULL, NULL, "pspp-stock-select");
-
-  gtk_action_connect_proxy (selector->action, GTK_WIDGET (selector));
 
   gtk_container_add (GTK_CONTAINER (selector), selector->arrow);
 
   gtk_widget_show (selector->arrow);
 
-  g_signal_connect_swapped (selector->action, "activate", G_CALLBACK (on_activate), selector);
-
   selector->selecting = FALSE;
 
   selector->source = NULL;
@@ -627,8 +623,10 @@ select_selection (PsppireSelector *selector)
    or other event which causes the selector's action to occur.
  */
 static void
-on_activate (PsppireSelector *selector, gpointer data)
+on_click (GtkButton *b)
 {
+  PsppireSelector *selector = PSPPIRE_SELECTOR (b);
+
   switch (selector->direction)
     {
     case PSPPIRE_SELECTOR_SOURCE_TO_DEST:
@@ -641,6 +639,10 @@ on_activate (PsppireSelector *selector, gpointer data)
       g_assert_not_reached ();
       break;
     }
+
+  if (GTK_BUTTON_CLASS (parent_class)->clicked)
+    GTK_BUTTON_CLASS (parent_class)->clicked (b);
+
 }
 
 static gboolean
index 028af187ea6b3cf2e21224b13c711f59c1cc798a..af3d45a372f6d8b6f5235b351cef94294409bae5 100644 (file)
@@ -71,7 +71,6 @@ struct _PsppireSelector
 
   /* <private> */
   GtkWidget *arrow;
-  GtkAction *action;
 
   gboolean dispose_has_run;
 
index b5cf0d3345d27cc45474bcc24e3cbe53c6562c0c..5ccbca5cb5660635a982b09ae4965a925ca59ae0 100644 (file)
@@ -600,6 +600,8 @@ syntax_pick_filename (PsppireWindow *window)
                                 GTK_STOCK_SAVE,   GTK_RESPONSE_ACCEPT,
                                 NULL);
 
+  g_object_set (dialog, "local-only", FALSE, NULL);
+
   filter = gtk_file_filter_new ();
   gtk_file_filter_set_name (filter, _("Syntax Files (*.sps) "));
   gtk_file_filter_add_pattern (filter, "*.sps");
diff --git a/src/ui/gui/psppire-val-chooser.c b/src/ui/gui/psppire-val-chooser.c
new file mode 100644 (file)
index 0000000..59225e2
--- /dev/null
@@ -0,0 +1,713 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  Free Software Foundation
+
+   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 <gtk/gtk.h>
+#include "psppire-val-chooser.h"
+
+#include "libpspp/str.h"
+
+
+#include "ui/syntax-gen.h"
+
+#include <gettext.h>
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+static void psppire_val_chooser_base_finalize (PsppireValChooserClass *, gpointer);
+static void psppire_val_chooser_base_init     (PsppireValChooserClass *class);
+static void psppire_val_chooser_class_init    (PsppireValChooserClass *class);
+static void psppire_val_chooser_init          (PsppireValChooser      *vc);
+
+static void psppire_val_chooser_realize       (GtkWidget *w);
+
+
+
+GType
+psppire_val_chooser_get_type (void)
+{
+  static GType psppire_val_chooser_type = 0;
+
+  if (!psppire_val_chooser_type)
+    {
+      static const GTypeInfo psppire_val_chooser_info =
+      {
+       sizeof (PsppireValChooserClass),
+       (GBaseInitFunc) psppire_val_chooser_base_init,
+        (GBaseFinalizeFunc) psppire_val_chooser_base_finalize,
+       (GClassInitFunc)psppire_val_chooser_class_init,
+       (GClassFinalizeFunc) NULL,
+       NULL,
+        sizeof (PsppireValChooser),
+       0,
+       (GInstanceInitFunc) psppire_val_chooser_init,
+      };
+
+      psppire_val_chooser_type =
+       g_type_register_static (GTK_TYPE_FRAME, "PsppireValChooser",
+                               &psppire_val_chooser_info, 0);
+    }
+
+  return psppire_val_chooser_type;
+}
+
+
+static void
+psppire_val_chooser_finalize (GObject *object)
+{
+
+}
+
+/* Properties */
+enum
+{
+  PROP_0,
+  PROP_IS_STRING,
+  PROP_SHOW_ELSE
+};
+
+
+enum 
+  {
+    VC_VALUE,
+    VC_SYSMIS,
+    VC_MISSING,
+    VC_RANGE,
+    VC_LOW_UP,
+    VC_HIGH_DOWN,
+    VC_ELSE
+  };
+
+static void
+psppire_val_chooser_set_property (GObject         *object,
+                              guint            prop_id,
+                              const GValue    *value,
+                              GParamSpec      *pspec)
+{
+  PsppireValChooser *vr = PSPPIRE_VAL_CHOOSER (object);
+
+  switch (prop_id)
+    {
+    case PROP_SHOW_ELSE:
+      {
+       gboolean x = g_value_get_boolean (value);
+       gtk_widget_set_visible (GTK_WIDGET (vr->rw[VC_ELSE].rb), x);
+       gtk_widget_set_visible (GTK_WIDGET (vr->rw[VC_ELSE].label), x);
+      }
+      break;
+    case PROP_IS_STRING:
+      vr->input_var_is_string = g_value_get_boolean (value);
+      gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[VC_SYSMIS].rb), !vr->input_var_is_string);
+      gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[VC_MISSING].rb), !vr->input_var_is_string);
+      gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[VC_RANGE].rb), !vr->input_var_is_string);
+      gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[VC_LOW_UP].rb), !vr->input_var_is_string);      
+      gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[VC_HIGH_DOWN].rb), !vr->input_var_is_string);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    };
+}
+
+
+static void
+psppire_val_chooser_get_property (GObject         *object,
+                              guint            prop_id,
+                              GValue          *value,
+                              GParamSpec      *pspec)
+{
+  PsppireValChooser *vr = PSPPIRE_VAL_CHOOSER (object);
+
+  switch (prop_id)
+    {
+    case PROP_SHOW_ELSE:
+      {
+       gboolean x =
+         gtk_widget_get_visible (GTK_WIDGET (vr->rw[VC_ELSE].rb));
+       g_value_set_boolean (value, x);
+      }
+      break;
+    case PROP_IS_STRING:
+      g_value_set_boolean (value, vr->input_var_is_string);
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    };
+}
+
+
+static GObjectClass * parent_class = NULL;
+
+static void
+psppire_val_chooser_class_init (PsppireValChooserClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+
+  GParamSpec *is_string_spec =
+    g_param_spec_boolean ("is-string",
+                         "String Value",
+                         "Should the value range be a string value",
+                         FALSE,
+                         G_PARAM_READWRITE);
+
+  GParamSpec *show_else_spec =
+    g_param_spec_boolean ("show-else",
+                         "Show Else",
+                         "Should the \"All other values\" item be visible",
+                         TRUE,
+                         G_PARAM_READWRITE);
+
+
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class->set_property = psppire_val_chooser_set_property;
+  object_class->get_property = psppire_val_chooser_get_property;
+
+  widget_class->realize = psppire_val_chooser_realize;
+
+  g_object_class_install_property (object_class,
+                                   PROP_IS_STRING,
+                                   is_string_spec);
+
+  g_object_class_install_property (object_class,
+                                   PROP_SHOW_ELSE,
+                                   show_else_spec);
+}
+
+
+static void
+psppire_val_chooser_base_init (PsppireValChooserClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->finalize = psppire_val_chooser_finalize;
+}
+
+
+
+static void
+psppire_val_chooser_base_finalize (PsppireValChooserClass *class,
+                                gpointer class_data)
+{
+
+}
+
+
+/* Set the focus of B to follow the sensitivity of A */
+static void
+focus_follows_sensitivity (GtkWidget *a, GParamSpec *pspec, GtkWidget *b)
+{
+  gboolean sens = gtk_widget_get_sensitive (a);
+
+  g_object_set (b, "has-focus", sens, NULL);
+}
+
+
+struct layout;
+typedef GtkWidget *filler_f (struct layout *, struct range_widgets *);
+typedef void set_f (PsppireValChooser *, struct old_value *, const struct range_widgets *);
+
+struct layout
+{
+  const gchar *label;
+  filler_f *fill;
+  set_f *set;
+};
+
+
+
+static void simple_set (PsppireValChooser *vr, struct old_value *ov, const struct range_widgets *rw)
+{
+  const gchar *text = gtk_entry_get_text (rw->e1);
+
+  if ( vr->input_var_is_string)
+    {
+      ov->type = OV_STRING;
+      ov->v.s = g_strdup (text);
+    }
+  else
+    {
+      ov->type = OV_NUMERIC;
+      ov->v.v = g_strtod (text, 0);
+    }
+}
+
+static void lo_up_set (PsppireValChooser *vr, struct old_value *ov, const struct range_widgets  *rw)
+{
+  const gchar *text = gtk_entry_get_text (rw->e1);
+  
+  ov->type = OV_LOW_UP;
+  ov->v.range[1] = g_strtod (text, 0);
+}
+
+
+static void hi_down_set (PsppireValChooser *vr, struct old_value *ov, const struct range_widgets *rw)
+{
+  const gchar *text = gtk_entry_get_text (rw->e1);
+  
+  ov->type = OV_HIGH_DOWN;
+  ov->v.range[0] = g_strtod (text, 0);
+}
+
+static void missing_set (PsppireValChooser *vr, struct old_value *ov, const struct range_widgets *l)
+{
+  ov->type = OV_MISSING;
+}
+
+
+static void sysmis_set (PsppireValChooser *vr, struct old_value *ov, const struct range_widgets *l)
+{
+  ov->type = OV_SYSMIS;
+}
+
+static void else_set (PsppireValChooser *vr, struct old_value *ov, const struct range_widgets *l)
+{
+  ov->type = OV_ELSE;
+}
+
+
+static void range_set (PsppireValChooser *vr, struct old_value *ov, const struct range_widgets *rw)
+{
+  const gchar *text = gtk_entry_get_text (rw->e1);
+
+  ov->type = OV_RANGE;
+  ov->v.range[0] = g_strtod (text, 0);
+  
+  text = gtk_entry_get_text (rw->e2);
+  ov->v.range[1] = g_strtod (text, 0);
+}
+
+static GtkWidget * range_entry (struct layout *l, struct range_widgets *rw)
+{
+  GtkWidget *vbox = gtk_vbox_new (3, FALSE);
+  GtkWidget *entrylo = gtk_entry_new ();
+  GtkWidget *label = gtk_label_new (_("through"));
+  GtkWidget *entryhi = gtk_entry_new ();
+
+  rw->e1 = GTK_ENTRY (entrylo);
+  rw->e2 = GTK_ENTRY (entryhi);
+
+  gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+  g_signal_connect (vbox, "notify::sensitive", G_CALLBACK (focus_follows_sensitivity), entrylo);
+
+  gtk_box_pack_start (GTK_BOX (vbox), entrylo, TRUE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), entryhi, TRUE, TRUE, 0);
+  return vbox;
+}
+
+static GtkWidget * simple_entry (struct layout *l, struct range_widgets *rw)
+{
+  GtkWidget *entry = gtk_entry_new ();
+
+  rw->e1 = GTK_ENTRY (entry);
+
+  g_signal_connect (entry, "notify::sensitive", G_CALLBACK (focus_follows_sensitivity), entry);
+  return entry;
+}
+
+
+static struct layout range_opt[n_VAL_CHOOSER_BUTTONS]= 
+  {
+    {N_("Value:"),                    simple_entry, simple_set },
+    {N_("System Missing"),            NULL,         sysmis_set },
+    {N_("System or User Missing"),    NULL,         missing_set},
+    {N_("Range:"),                    range_entry,  range_set  },
+    {N_("Range, LOWEST thru value"),  simple_entry, lo_up_set  },
+    {N_("Range, value thru HIGHEST"), simple_entry, hi_down_set},
+    {N_("All other values"),          NULL,         else_set   }
+  };
+
+static void
+set_sensitivity_from_toggle (GtkToggleButton *togglebutton,  GtkWidget *w)
+{
+  gboolean active = gtk_toggle_button_get_active (togglebutton);
+
+  gtk_widget_set_sensitive (w, active);
+}
+
+static void
+psppire_val_chooser_init (PsppireValChooser *vr)
+{
+  gint i;
+  GtkWidget *aln = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+  GtkWidget *table = gtk_table_new (11, 2, FALSE);
+  GSList *group = NULL;
+  gint row = 0;
+
+  gtk_alignment_set_padding (GTK_ALIGNMENT (aln), 0, 0, 5, 5);
+
+  vr->input_var_is_string = FALSE;
+
+  for (i = 0; i < n_VAL_CHOOSER_BUTTONS; ++i)
+    {
+      struct layout *l = &range_opt[i];
+      vr->rw[i].label = GTK_LABEL (gtk_label_new (gettext (l->label)));
+      vr->rw[i].rb = GTK_TOGGLE_BUTTON (gtk_radio_button_new (group));
+
+      gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[i].label), FALSE);
+      g_signal_connect (vr->rw[i].rb, "toggled", G_CALLBACK (set_sensitivity_from_toggle), vr->rw[i].label);
+
+      gtk_misc_set_alignment (GTK_MISC (vr->rw[i].label), 0, 0.5);
+
+      group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (vr->rw[i].rb));
+
+      gtk_table_attach_defaults (GTK_TABLE (table), GTK_WIDGET (vr->rw[i].rb), 0, 1,
+                                row, row + 1);
+
+
+      gtk_table_attach_defaults (GTK_TABLE (table), GTK_WIDGET (vr->rw[i].label), 1, 2,
+                                row, row + 1);
+      ++row;
+
+      if (l->fill)
+       {
+         GtkWidget *fill = l->fill (l, &vr->rw[i]);
+
+         gtk_widget_set_sensitive (fill, FALSE);
+
+         gtk_table_attach_defaults (GTK_TABLE (table), fill, 1, 2,
+                                row, row + 1);
+         ++row;
+
+         g_signal_connect (vr->rw[i].rb, "toggled", G_CALLBACK (set_sensitivity_from_toggle), fill);
+       }
+    }
+
+  gtk_frame_set_shadow_type (GTK_FRAME (vr), GTK_SHADOW_ETCHED_IN);
+
+  gtk_container_add (GTK_CONTAINER (aln), table);
+  gtk_container_add (GTK_CONTAINER (vr), aln);
+
+  gtk_widget_show_all (aln);
+}
+
+
+GtkWidget*
+psppire_val_chooser_new (void)
+{
+  return GTK_WIDGET (g_object_new (psppire_val_chooser_get_type (), NULL));
+}
+
+
+
+static void
+psppire_val_chooser_realize (GtkWidget *w)
+{
+  PsppireValChooser *vr = PSPPIRE_VAL_CHOOSER (w);
+
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(vr->rw[0].rb), TRUE);
+  gtk_toggle_button_toggled (GTK_TOGGLE_BUTTON (vr->rw[0].rb));
+
+  /* Chain up to the parent class */
+  GTK_WIDGET_CLASS (parent_class)->realize (w);
+}
+
+
+\f
+
+/* A boxed type representing a value, or a range of values which may
+   potentially be replaced by something */
+
+
+static struct old_value *
+old_value_copy (struct old_value *ov)
+{
+  struct old_value *copy = g_memdup (ov, sizeof (*copy));
+
+  if ( ov->type == OV_STRING )
+    copy->v.s = g_strdup (ov->v.s);
+
+  return copy;
+}
+
+
+static void
+old_value_free (struct old_value *ov)
+{
+  if (ov->type == OV_STRING)
+    g_free (ov->v.s);
+  g_free (ov);
+}
+
+static void
+old_value_to_string (const GValue *src, GValue *dest)
+{
+  const struct old_value *ov = g_value_get_boxed (src);
+
+  switch (ov->type)
+    {
+    case OV_NUMERIC:
+      {
+       gchar *text = g_strdup_printf ("%g", ov->v.v);
+       g_value_set_string (dest, text);
+       g_free (text);
+      }
+      break;
+    case OV_STRING:
+      g_value_set_string (dest, ov->v.s);
+      break;
+    case OV_MISSING:
+      g_value_set_string (dest, "MISSING");
+      break;
+    case OV_SYSMIS:
+      g_value_set_string (dest, "SYSMIS");
+      break;
+    case OV_ELSE:
+      g_value_set_string (dest, "ELSE");
+      break;
+    case OV_RANGE:
+      {
+       gchar *text;
+       char en_dash[6] = {0,0,0,0,0,0};
+
+       g_unichar_to_utf8 (0x2013, en_dash);
+
+       text = g_strdup_printf ("%g %s %g",
+                                      ov->v.range[0],
+                                      en_dash,
+                                      ov->v.range[1]);
+       g_value_set_string (dest, text);
+       g_free (text);
+      }
+      break;
+    case OV_LOW_UP:
+      {
+       gchar *text;
+       char en_dash[6] = {0,0,0,0,0,0};
+
+       g_unichar_to_utf8 (0x2013, en_dash);
+
+       text = g_strdup_printf ("LOWEST %s %g",
+                               en_dash,
+                               ov->v.range[1]);
+
+       g_value_set_string (dest, text);
+       g_free (text);
+      }
+      break;
+    case OV_HIGH_DOWN:
+      {
+       gchar *text;
+       char en_dash[6] = {0,0,0,0,0,0};
+
+       g_unichar_to_utf8 (0x2013, en_dash);
+
+       text = g_strdup_printf ("%g %s HIGHEST",
+                               ov->v.range[0],
+                               en_dash);
+
+       g_value_set_string (dest, text);
+       g_free (text);
+      }
+      break;
+    default:
+      g_warning ("Invalid type in old recode value");
+      g_value_set_string (dest, "???");
+      break;
+    };
+}
+
+GType
+old_value_get_type (void)
+{
+  static GType t = 0;
+
+  if (t == 0 )
+    {
+      t = g_boxed_type_register_static  ("psppire-recode-old-values",
+                                        (GBoxedCopyFunc) old_value_copy,
+                                        (GBoxedFreeFunc) old_value_free);
+
+      g_value_register_transform_func     (t, G_TYPE_STRING,
+                                          old_value_to_string);
+    }
+
+  return t;
+}
+
+\f
+
+/* Generate a syntax fragment for NV and append it to STR */
+void
+old_value_append_syntax (GString *str, const struct old_value *ov)
+{
+  switch (ov->type)
+    {
+    case OV_NUMERIC:
+      g_string_append_printf (str, "%g", ov->v.v);
+      break;
+    case OV_STRING:
+      {
+       struct string ds = DS_EMPTY_INITIALIZER;
+       syntax_gen_string (&ds, ss_cstr (ov->v.s));
+       g_string_append (str, ds_cstr (&ds));
+       ds_destroy (&ds);
+      }
+      break;
+    case OV_MISSING:
+      g_string_append (str, "MISSING");
+      break;
+    case OV_SYSMIS:
+      g_string_append (str, "SYSMIS");
+      break;
+    case OV_ELSE:
+      g_string_append (str, "ELSE");
+      break;
+    case OV_RANGE:
+      g_string_append_printf (str, "%g THRU %g",
+                             ov->v.range[0],
+                             ov->v.range[1]);
+      break;
+    case OV_LOW_UP:
+      g_string_append_printf (str, "LOWEST THRU %g",
+                             ov->v.range[1]);
+      break;
+    case OV_HIGH_DOWN:
+      g_string_append_printf (str, "%g THRU HIGHEST",
+                             ov->v.range[0]);
+      break;
+    default:
+      g_warning ("Invalid type in old recode value");
+      g_string_append (str, "???");
+      break;
+    };
+}
+
+
+
+/* Set OV according to the current state of VR */
+void
+psppire_val_chooser_get_status (PsppireValChooser *vr, struct old_value *ov)
+{
+  int i;
+
+  for (i = 0; i < n_VAL_CHOOSER_BUTTONS; ++i)
+    {
+      if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (vr->rw[i].rb)))
+       {
+         break;
+       }
+    }
+
+  range_opt[i].set (vr, ov, &vr->rw[i]);
+}
+
+/* This might need to be changed to something less naive.
+   In particular, what happends with dates, etc?
+ */
+static gchar *
+num_to_string (gdouble x)
+{
+  return g_strdup_printf ("%g", x);
+}
+
+
+/* Set VR according to the value of OV */
+void
+psppire_val_chooser_set_status (PsppireValChooser *vr, const struct old_value *ov)
+{
+  gint i;
+  if ( !ov )
+    return;
+
+  for (i = 0; i < n_VAL_CHOOSER_BUTTONS; ++i)
+    {
+      if (vr->rw[i].e1)
+       gtk_entry_set_text (vr->rw[i].e1, "");
+
+      if (vr->rw[i].e2)
+       gtk_entry_set_text (vr->rw[i].e2, "");
+    }
+
+  switch (ov->type)
+    {
+    case OV_STRING:
+      gtk_toggle_button_set_active (vr->rw[0].rb, TRUE);
+      gtk_entry_set_text (vr->rw[0].e1, ov->v.s);
+      break;
+      
+    case OV_NUMERIC:
+      {
+       gchar *str;
+       gtk_toggle_button_set_active (vr->rw[0].rb, TRUE);
+       
+       str = num_to_string (ov->v.v);
+       
+       gtk_entry_set_text (vr->rw[0].e1, str);
+       g_free (str);
+      }
+      break;
+
+      case OV_SYSMIS:
+       gtk_toggle_button_set_active (vr->rw[VC_SYSMIS].rb, TRUE);
+       break;
+
+      case OV_MISSING:
+       gtk_toggle_button_set_active (vr->rw[VC_MISSING].rb, TRUE);
+       break;
+
+      case OV_RANGE:
+       {
+         gchar *str = num_to_string (ov->v.range[0]);
+         gtk_toggle_button_set_active (vr->rw[VC_RANGE].rb, TRUE);
+         gtk_entry_set_text (vr->rw[VC_RANGE].e1, str);
+
+         g_free (str);
+
+         str = num_to_string (ov->v.range[1]);
+         gtk_entry_set_text (vr->rw[VC_RANGE].e2, str);
+         g_free (str);
+       }
+       break;
+
+      case OV_LOW_UP:
+       {
+         gchar *str = num_to_string (ov->v.range[1]);
+
+         gtk_toggle_button_set_active (vr->rw[VC_LOW_UP].rb, TRUE);
+
+         gtk_entry_set_text (vr->rw[VC_LOW_UP].e1, str);
+
+         g_free (str);
+       }
+       break;
+
+
+      case OV_HIGH_DOWN:
+       {
+         gchar *str = num_to_string (ov->v.range[0]);
+
+         gtk_toggle_button_set_active (vr->rw[VC_HIGH_DOWN].rb, TRUE);
+
+         gtk_entry_set_text (vr->rw[VC_HIGH_DOWN].e1, str);
+
+         g_free (str);
+       }
+       break;
+
+      case OV_ELSE:
+       gtk_toggle_button_set_active (vr->rw[VC_ELSE].rb, TRUE);
+       break;
+
+    default:
+      g_warning ("Unknown old value type");
+      break;
+    };
+}
diff --git a/src/ui/gui/psppire-val-chooser.h b/src/ui/gui/psppire-val-chooser.h
new file mode 100644 (file)
index 0000000..5c8175b
--- /dev/null
@@ -0,0 +1,105 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  Free Software Foundation
+
+   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/>. */
+
+
+#ifndef __PSPPIRE_VAL_CHOOSER_H__
+#define __PSPPIRE_VAL_CHOOSER_H__
+
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+
+G_BEGIN_DECLS
+
+#define PSPPIRE_VAL_CHOOSER_TYPE            (psppire_val_chooser_get_type ())
+#define PSPPIRE_VAL_CHOOSER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), PSPPIRE_VAL_CHOOSER_TYPE, PsppireValChooser))
+#define PSPPIRE_VAL_CHOOSER_CLASS(class)    (G_TYPE_CHECK_CLASS_CAST ((class), \
+    PSPPIRE_VAL_CHOOSER_TYPE, PsppireValChooserClass))
+#define PSPPIRE_IS_VAL_CHOOSER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+    PSPPIRE_VAL_CHOOSER_TYPE))
+#define PSPPIRE_IS_VAL_CHOOSER_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), \
+    PSPPIRE_VAL_CHOOSER_TYPE))
+
+
+typedef struct _PsppireValChooser       PsppireValChooser;
+typedef struct _PsppireValChooserClass  PsppireValChooserClass;
+
+#define n_VAL_CHOOSER_BUTTONS 7
+
+struct range_widgets
+{
+  GtkLabel *label;
+  GtkToggleButton *rb;
+  GtkEntry *e1;
+  GtkEntry *e2;
+};
+
+struct _PsppireValChooser
+{
+  GtkFrame parent;
+
+  struct range_widgets rw [n_VAL_CHOOSER_BUTTONS];
+  gboolean input_var_is_string;
+};
+
+struct _PsppireValChooserClass
+{
+  GtkTreeViewClass parent_class;
+
+};
+
+GType      psppire_val_chooser_get_type        (void);
+
+
+G_END_DECLS
+
+
+\f
+
+enum old_value_type
+ {
+   OV_NUMERIC,
+   OV_STRING,
+   OV_SYSMIS,
+   OV_MISSING,
+   OV_RANGE,
+   OV_LOW_UP,
+   OV_HIGH_DOWN,
+   OV_ELSE
+ };
+
+struct old_value
+ {
+   enum old_value_type type;
+   union {
+     double v;
+     gchar *s;
+     double range[2];
+   } v;
+ };
+
+GType old_value_get_type (void);
+
+void old_value_append_syntax (GString *str, const struct old_value *ov);
+
+void psppire_val_chooser_get_status (PsppireValChooser *vr, struct old_value *ov);
+void psppire_val_chooser_set_status (PsppireValChooser *vr, const struct old_value *ov);
+
+
+
+#endif /* __PSPPIRE_VAL_CHOOSER_H__ */
index edaa372670755020b0cfc9594e8cb0c6d5fde3db..2b521970ceec0226bf4af930794679bf65a8abc4 100644 (file)
@@ -38,7 +38,6 @@
 #include "psppire-window-register.h"
 #include "psppire.h"
 
-static void psppire_window_base_finalize (PsppireWindowClass *, gpointer);
 static void psppire_window_base_init     (PsppireWindowClass *class);
 static void psppire_window_class_init    (PsppireWindowClass *class);
 static void psppire_window_init          (PsppireWindow      *window);
@@ -57,7 +56,7 @@ psppire_window_get_type (void)
       {
        sizeof (PsppireWindowClass),
        (GBaseInitFunc) psppire_window_base_init,
-        (GBaseFinalizeFunc) psppire_window_base_finalize,
+        (GBaseFinalizeFunc) NULL,
        (GClassInitFunc) psppire_window_class_init,
        (GClassFinalizeFunc) NULL,
        NULL,
@@ -85,12 +84,6 @@ enum
 };
 
 
-gchar *
-uniquify (const gchar *str, int *x)
-{
-  return g_strdup_printf ("%s%d", str, (*x)++);
-}
-
 static void
 psppire_window_set_title (PsppireWindow *window)
 {
@@ -328,12 +321,6 @@ psppire_window_base_init (PsppireWindowClass *class)
 
 
 
-static void
-psppire_window_base_finalize (PsppireWindowClass *class,
-                               gpointer class_data)
-{
-}
-
 static void
 menu_toggled (GtkCheckMenuItem *mi, gpointer data)
 {
@@ -722,6 +709,7 @@ psppire_window_load (PsppireWindow *w, const gchar *file)
 GtkWidget *
 psppire_window_file_chooser_dialog (PsppireWindow *toplevel)
 {
+  GtkFileFilter *filter = gtk_file_filter_new ();
   GtkWidget *dialog =
     gtk_file_chooser_dialog_new (_("Open"),
                                 GTK_WINDOW (toplevel),
@@ -730,9 +718,8 @@ psppire_window_file_chooser_dialog (PsppireWindow *toplevel)
                                 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                                 NULL);
 
-  GtkFileFilter *filter;
+  g_object_set (dialog, "local-only", FALSE, NULL);
 
-  filter = gtk_file_filter_new ();
   gtk_file_filter_set_name (filter, _("Data and Syntax Files"));
   gtk_file_filter_add_pattern (filter, "*.sav");
   gtk_file_filter_add_pattern (filter, "*.SAV");
index 55376644f1b00cda4f80431ec175cab1baa5be66..dc14067d0b1cd6c581d4f19a09e797e533708d43 100644 (file)
@@ -38,6 +38,8 @@
 #include <ui/gui/psppire-dialog.h>
 #include <ui/gui/psppire-var-store.h>
 
+#include "psppire-val-chooser.h"
+
 #include <ui/syntax-gen.h>
 
 #include "psppire-acr.h"
@@ -143,151 +145,6 @@ new_value_get_type (void)
 }
 
 
-\f
-
-
-/* A boxed type representing a value, or a range of values which may
-   potentially be replaced by something */
-
-enum old_value_type
- {
-   OV_NUMERIC,
-   OV_STRING,
-   OV_SYSMIS,
-   OV_MISSING,
-   OV_RANGE,
-   OV_LOW_UP,
-   OV_HIGH_DOWN,
-   OV_ELSE
- };
-
-struct old_value
- {
-   enum old_value_type type;
-   union {
-     double v;
-     gchar *s;
-     double range[2];
-   } v;
- };
-
-
-static struct old_value *
-old_value_copy (struct old_value *ov)
-{
-  struct old_value *copy = g_memdup (ov, sizeof (*copy));
-
-  if ( ov->type == OV_STRING )
-    copy->v.s = g_strdup (ov->v.s);
-
-  return copy;
-}
-
-
-static void
-old_value_free (struct old_value *ov)
-{
-  if (ov->type == OV_STRING)
-    g_free (ov->v.s);
-  g_free (ov);
-}
-
-static void
-old_value_to_string (const GValue *src, GValue *dest)
-{
-  const struct old_value *ov = g_value_get_boxed (src);
-
-  switch (ov->type)
-    {
-    case OV_NUMERIC:
-      {
-       gchar *text = g_strdup_printf ("%g", ov->v.v);
-       g_value_set_string (dest, text);
-       g_free (text);
-      }
-      break;
-    case OV_STRING:
-      g_value_set_string (dest, ov->v.s);
-      break;
-    case OV_MISSING:
-      g_value_set_string (dest, "MISSING");
-      break;
-    case OV_SYSMIS:
-      g_value_set_string (dest, "SYSMIS");
-      break;
-    case OV_ELSE:
-      g_value_set_string (dest, "ELSE");
-      break;
-    case OV_RANGE:
-      {
-       gchar *text;
-       char en_dash[6] = {0,0,0,0,0,0};
-
-       g_unichar_to_utf8 (0x2013, en_dash);
-
-       text = g_strdup_printf ("%g %s %g",
-                                      ov->v.range[0],
-                                      en_dash,
-                                      ov->v.range[1]);
-       g_value_set_string (dest, text);
-       g_free (text);
-      }
-      break;
-    case OV_LOW_UP:
-      {
-       gchar *text;
-       char en_dash[6] = {0,0,0,0,0,0};
-
-       g_unichar_to_utf8 (0x2013, en_dash);
-
-       text = g_strdup_printf ("LOWEST %s %g",
-                               en_dash,
-                               ov->v.range[1]);
-
-       g_value_set_string (dest, text);
-       g_free (text);
-      }
-      break;
-    case OV_HIGH_DOWN:
-      {
-       gchar *text;
-       char en_dash[6] = {0,0,0,0,0,0};
-
-       g_unichar_to_utf8 (0x2013, en_dash);
-
-       text = g_strdup_printf ("%g %s HIGHEST",
-                               ov->v.range[0],
-                               en_dash);
-
-       g_value_set_string (dest, text);
-       g_free (text);
-      }
-      break;
-    default:
-      g_warning ("Invalid type in old recode value");
-      g_value_set_string (dest, "???");
-      break;
-    };
-}
-
-static GType
-old_value_get_type (void)
-{
-  static GType t = 0;
-
-  if (t == 0 )
-    {
-      t = g_boxed_type_register_static  ("psppire-recode-old-values",
-                                        (GBoxedCopyFunc) old_value_copy,
-                                        (GBoxedFreeFunc) old_value_free);
-
-      g_value_register_transform_func     (t, G_TYPE_STRING,
-                                          old_value_to_string);
-    }
-
-  return t;
-}
-
 \f
 
 enum
@@ -295,13 +152,6 @@ enum
     BUTTON_NEW_VALUE,
     BUTTON_NEW_COPY,
     BUTTON_NEW_SYSMIS,
-    BUTTON_OLD_VALUE,
-    BUTTON_OLD_SYSMIS,
-    BUTTON_OLD_MISSING,
-    BUTTON_OLD_RANGE,
-    BUTTON_OLD_LOW_UP,
-    BUTTON_OLD_HIGH_DOWN,
-    BUTTON_OLD_ELSE,
     n_BUTTONS
   };
 
@@ -320,13 +170,9 @@ struct recode_dialog
   GtkWidget *convert_button;
   GtkWidget *new_copy_label;
 
-  GtkWidget *ov_value_entry;
   GtkWidget *new_value_entry;
 
-  GtkWidget *ov_range_lower_entry;
-  GtkWidget *ov_range_upper_entry;
-  GtkWidget *ov_low_up_entry;
-  GtkWidget *ov_high_down_entry;
+  GtkWidget *old_value_chooser;
 
   GtkListStore *value_map;
 
@@ -364,7 +210,7 @@ refresh (PsppireDialog *dialog, struct recode_dialog *rd)
   gtk_widget_set_sensitive (rd->new_name_entry, FALSE);
   gtk_widget_set_sensitive (rd->new_label_entry, FALSE);
 
-  if ( rd->different )
+  if ( rd->different && rd->varmap )
     g_hash_table_remove_all (rd->varmap);
 
   gtk_list_store_clear (GTK_LIST_STORE (rd->value_map));
@@ -416,11 +262,6 @@ dialog_state_valid (gpointer data)
 static void
 on_old_new_show (struct recode_dialog *rd)
 {
-  gtk_toggle_button_set_active
-    (GTK_TOGGLE_BUTTON (rd->toggle[BUTTON_OLD_VALUE]), TRUE);
-
-  g_signal_emit_by_name (rd->toggle[BUTTON_OLD_VALUE], "toggled");
-
   gtk_toggle_button_set_active
     (GTK_TOGGLE_BUTTON (rd->toggle[BUTTON_NEW_VALUE]), TRUE);
 
@@ -545,101 +386,7 @@ on_acr_selection_change (GtkTreeSelection *selection, gpointer data)
       g_value_unset (&nv_value);
     }
 
-  if ( ov )
-    {
-    switch (ov->type)
-      {
-      case OV_STRING:
-         gtk_toggle_button_set_active
-           (GTK_TOGGLE_BUTTON (rd->toggle [BUTTON_OLD_VALUE]), TRUE);
-
-         gtk_entry_set_text (GTK_ENTRY (rd->ov_value_entry), ov->v.s);
-       break;
-
-      case OV_NUMERIC:
-       {
-         gchar *str;
-
-         gtk_toggle_button_set_active
-           (GTK_TOGGLE_BUTTON (rd->toggle [BUTTON_OLD_VALUE]), TRUE);
-
-         str = num_to_string (ov->v.v);
-
-         gtk_entry_set_text (GTK_ENTRY (rd->ov_value_entry), str);
-
-         g_free (str);
-       }
-       break;
-
-      case OV_SYSMIS:
-       gtk_toggle_button_set_active
-         (GTK_TOGGLE_BUTTON (rd->toggle [BUTTON_OLD_SYSMIS]), TRUE);
-       break;
-
-      case OV_MISSING:
-       gtk_toggle_button_set_active
-         (GTK_TOGGLE_BUTTON (rd->toggle [BUTTON_OLD_MISSING]), TRUE);
-       break;
-
-      case OV_RANGE:
-       {
-         gchar *str;
-
-         gtk_toggle_button_set_active
-           (GTK_TOGGLE_BUTTON (rd->toggle [BUTTON_OLD_RANGE]), TRUE);
-
-         str = num_to_string (ov->v.range[0]);
-
-         gtk_entry_set_text (GTK_ENTRY (rd->ov_range_lower_entry), str);
-
-         g_free (str);
-
-
-         str = num_to_string (ov->v.range[1]);
-
-         gtk_entry_set_text (GTK_ENTRY (rd->ov_range_upper_entry), str);
-
-         g_free (str);
-       }
-       break;
-
-      case OV_LOW_UP:
-       {
-         gchar *str = num_to_string (ov->v.range[1]);
-
-         gtk_toggle_button_set_active
-           (GTK_TOGGLE_BUTTON (rd->toggle [BUTTON_OLD_LOW_UP]), TRUE);
-
-         gtk_entry_set_text (GTK_ENTRY (rd->ov_low_up_entry), str);
-
-         g_free (str);
-       }
-       break;
-
-      case OV_HIGH_DOWN:
-       {
-         gchar *str = num_to_string (ov->v.range[0]);
-
-         gtk_toggle_button_set_active
-           (GTK_TOGGLE_BUTTON (rd->toggle [BUTTON_OLD_HIGH_DOWN]), TRUE);
-
-         gtk_entry_set_text (GTK_ENTRY (rd->ov_high_down_entry), str);
-
-         g_free (str);
-       }
-       break;
-
-      case OV_ELSE:
-       gtk_toggle_button_set_active
-         (GTK_TOGGLE_BUTTON (rd->toggle [BUTTON_OLD_ELSE]), TRUE);
-       break;
-
-      default:
-       g_warning ("Unknown old value type");
-       break;
-      };
-    g_value_unset (&ov_value);
-    }
+  psppire_val_chooser_set_status (PSPPIRE_VAL_CHOOSER (rd->old_value_chooser), ov);
 }
 
 /* Name-Label pair */
@@ -929,10 +676,6 @@ recode_dialog (PsppireDataWindow *de, gboolean diff)
       g_signal_connect (rd.change_button, "clicked",
                        G_CALLBACK (on_change_clicked),  &rd);
 
-#if 0
-      g_signal_connect (model, "row-inserted",
-                       G_CALLBACK (select_something), &rd);
-#endif
     }
 
   psppire_selector_set_allow (PSPPIRE_SELECTOR (selector), homogeneous_types);
@@ -944,24 +687,14 @@ recode_dialog (PsppireDataWindow *de, gboolean diff)
 
     rd.convert_button           = get_widget_assert (builder, "checkbutton2");
 
-    rd.ov_range_lower_entry = get_widget_assert (builder, "entry5");
-    rd.ov_range_upper_entry  = get_widget_assert (builder, "entry3");
-    rd.ov_low_up_entry       = get_widget_assert (builder, "entry6");
-    rd.ov_high_down_entry    = get_widget_assert (builder, "entry7");
+    rd.old_value_chooser = get_widget_assert (builder, "val-chooser");
 
     rd.new_value_entry = get_widget_assert (builder, "entry1");
-    rd.ov_value_entry  = get_widget_assert (builder, "entry2");
+
 
     rd.toggle[BUTTON_NEW_VALUE]  = get_widget_assert (builder, "radiobutton1");
     rd.toggle[BUTTON_NEW_SYSMIS] = get_widget_assert (builder, "radiobutton2");
     rd.toggle[BUTTON_NEW_COPY]   = get_widget_assert (builder, "radiobutton3");
-    rd.toggle[BUTTON_OLD_VALUE]  = get_widget_assert (builder, "radiobutton4");
-    rd.toggle[BUTTON_OLD_SYSMIS] = get_widget_assert (builder, "radiobutton6");
-    rd.toggle[BUTTON_OLD_MISSING]= get_widget_assert (builder, "radiobutton7");
-    rd.toggle[BUTTON_OLD_RANGE]  = get_widget_assert (builder, "radiobutton8");
-    rd.toggle[BUTTON_OLD_LOW_UP] = get_widget_assert (builder, "radiobutton10");
-    rd.toggle[BUTTON_OLD_HIGH_DOWN] = get_widget_assert (builder, "radiobutton5");
-    rd.toggle[BUTTON_OLD_ELSE]   = get_widget_assert (builder, "radiobutton11");
 
     rd.new_copy_label = get_widget_assert (builder, "label3");
     rd.strings_box    = get_widget_assert (builder, "table3");
@@ -1018,23 +751,6 @@ recode_dialog (PsppireDataWindow *de, gboolean diff)
     g_signal_connect (rd.toggle[BUTTON_NEW_VALUE], "toggled",
                      G_CALLBACK (toggle_sensitivity), rd.new_value_entry);
 
-    g_signal_connect (rd.toggle[BUTTON_OLD_VALUE], "toggled",
-                     G_CALLBACK (toggle_sensitivity), rd.ov_value_entry);
-
-    g_signal_connect (rd.toggle[BUTTON_OLD_RANGE], "toggled",
-                     G_CALLBACK (toggle_sensitivity),
-                     get_widget_assert (builder, "entry3"));
-
-    g_signal_connect (rd.toggle[BUTTON_OLD_RANGE], "toggled",
-                     G_CALLBACK (toggle_sensitivity),
-                     get_widget_assert (builder, "entry5"));
-
-    g_signal_connect (rd.toggle[BUTTON_OLD_LOW_UP], "toggled",
-                     G_CALLBACK (toggle_sensitivity), rd.ov_low_up_entry);
-
-    g_signal_connect (rd.toggle[BUTTON_OLD_HIGH_DOWN], "toggled",
-                     G_CALLBACK (toggle_sensitivity), rd.ov_high_down_entry);
-
     g_signal_connect (rd.string_button, "toggled",
                      G_CALLBACK (toggle_sensitivity), rd.width_entry);
 
@@ -1068,7 +784,8 @@ recode_dialog (PsppireDataWindow *de, gboolean diff)
       break;
     }
 
-  g_hash_table_destroy (rd.varmap);
+  if (rd.varmap)
+    g_hash_table_destroy (rd.varmap);
 
   gtk_list_store_clear (GTK_LIST_STORE (rd.value_map));
   g_object_unref (rd.value_map);
@@ -1080,70 +797,11 @@ recode_dialog (PsppireDataWindow *de, gboolean diff)
 static gboolean
 set_old_value (GValue *val, const struct recode_dialog *rd)
 {
-  const gchar *text = NULL;
-  struct old_value ov;
-  if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
-                                    (rd->toggle [BUTTON_OLD_VALUE])))
-    {
-      text = gtk_entry_get_text (GTK_ENTRY (rd->ov_value_entry));
-      if ( rd->input_var_is_string )
-       {
-         ov.type = OV_STRING;
-         ov.v.s = g_strdup (text);
-       }
-      else
-       {
-         ov.type = OV_NUMERIC;
-         ov.v.v = g_strtod (text, 0);
-       }
-    }
-  else if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
-                                         (rd->toggle [BUTTON_OLD_MISSING])))
-    {
-      ov.type = OV_MISSING;
-    }
-  else if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
-                                         (rd->toggle [BUTTON_OLD_SYSMIS])))
-    {
-      ov.type = OV_SYSMIS;
-    }
-  else if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
-                                         (rd->toggle [BUTTON_OLD_ELSE])))
-    {
-      ov.type = OV_ELSE;
-    }
-  else if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
-                                         (rd->toggle [BUTTON_OLD_RANGE])))
-    {
-      const gchar *text;
-      text = gtk_entry_get_text (GTK_ENTRY (rd->ov_range_lower_entry));
-
-      ov.type = OV_RANGE;
-      ov.v.range[0] = g_strtod (text, 0);
+  PsppireValChooser *vc = PSPPIRE_VAL_CHOOSER (rd->old_value_chooser);
 
-      text = gtk_entry_get_text (GTK_ENTRY (rd->ov_range_upper_entry));
-      ov.v.range[1] = g_strtod (text, 0);
-    }
-  else if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
-                                         (rd->toggle [BUTTON_OLD_LOW_UP])))
-    {
-      const gchar *text =
-       gtk_entry_get_text (GTK_ENTRY (rd->ov_low_up_entry));
+  struct old_value ov;
 
-      ov.type = OV_LOW_UP;
-      ov.v.range[1] = g_strtod (text, 0);
-    }
-  else if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
-                                         (rd->toggle [BUTTON_OLD_HIGH_DOWN])))
-    {
-      const gchar *text =
-       gtk_entry_get_text (GTK_ENTRY (rd->ov_high_down_entry));
-
-      ov.type = OV_HIGH_DOWN;
-      ov.v.range[0] = g_strtod (text, 0);
-    }
-  else
-    return FALSE;
+  psppire_val_chooser_get_status (vc, &ov);
 
   g_value_init (val, old_value_get_type ());
   g_value_set_boxed (val, &ov);
@@ -1202,7 +860,7 @@ set_new_value (GValue *val, const struct recode_dialog *rd)
 
 
 /* A function to set a value in a column in the ACR */
-gboolean
+static gboolean
 set_value (gint col, GValue  *val, gpointer data)
 {
   struct recode_dialog *rd = data;
@@ -1254,14 +912,8 @@ run_old_and_new_dialog (struct recode_dialog *rd)
 
     rd->input_var_is_string = var_is_alpha (v);
 
-    gtk_widget_set_sensitive (rd->toggle [BUTTON_OLD_SYSMIS],
-                             var_is_numeric (v));
-    gtk_widget_set_sensitive (rd->toggle [BUTTON_OLD_RANGE],
-                             var_is_numeric (v));
-    gtk_widget_set_sensitive (rd->toggle [BUTTON_OLD_LOW_UP],
-                             var_is_numeric (v));
-    gtk_widget_set_sensitive (rd->toggle [BUTTON_OLD_HIGH_DOWN],
-                             var_is_numeric (v));
+    g_object_set (rd->old_value_chooser, "is-string", rd->input_var_is_string, NULL);
+
     gtk_widget_set_sensitive (rd->toggle [BUTTON_NEW_SYSMIS],
                              var_is_numeric (v));
 
@@ -1318,54 +970,6 @@ new_value_append_syntax (GString *str, const struct new_value *nv)
 }
 
 
-/* Generate a syntax fragment for NV and append it to STR */
-static void
-old_value_append_syntax (GString *str, const struct old_value *ov)
-{
-  switch (ov->type)
-    {
-    case OV_NUMERIC:
-      g_string_append_printf (str, "%g", ov->v.v);
-      break;
-    case OV_STRING:
-      {
-       struct string ds = DS_EMPTY_INITIALIZER;
-       syntax_gen_string (&ds, ss_cstr (ov->v.s));
-       g_string_append (str, ds_cstr (&ds));
-       ds_destroy (&ds);
-      }
-      break;
-    case OV_MISSING:
-      g_string_append (str, "MISSING");
-      break;
-    case OV_SYSMIS:
-      g_string_append (str, "SYSMIS");
-      break;
-    case OV_ELSE:
-      g_string_append (str, "ELSE");
-      break;
-    case OV_RANGE:
-      g_string_append_printf (str, "%g THRU %g",
-                             ov->v.range[0],
-                             ov->v.range[1]);
-      break;
-    case OV_LOW_UP:
-      g_string_append_printf (str, "LOWEST THRU %g",
-                             ov->v.range[1]);
-      break;
-    case OV_HIGH_DOWN:
-      g_string_append_printf (str, "%g THRU HIGHEST",
-                             ov->v.range[0]);
-      break;
-    default:
-      g_warning ("Invalid type in old recode value");
-      g_string_append (str, "???");
-      break;
-    };
-}
-
-
-
 static char *
 generate_syntax (const struct recode_dialog *rd)
 {
index 45a3a6cc2c4fea79611996484ae8be214becbefe..f9b758279635b99104d11dcc53b0add4caa22185 100644 (file)
         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
         <property name="spacing">5</property>
         <child>
-          <object class="GtkFrame" id="frame2">
+          <object class="PsppireValChooser" id="val-chooser">
+           <property name="label" translatable="yes">Old Value</property>
             <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="label_xalign">0</property>
-            <child>
-              <object class="GtkAlignment" id="alignment3">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="left_padding">12</property>
-                <property name="right_padding">5</property>
-                <child>
-                  <object class="GtkTable" id="table2">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="n_rows">11</property>
-                    <property name="n_columns">2</property>
-                    <child>
-                      <object class="GtkAlignment" id="alignment11">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="xscale">0</property>
-                        <child>
-                          <object class="GtkEntry" id="entry7">
-                            <property name="visible">True</property>
-                            <property name="sensitive">False</property>
-                            <property name="can_focus">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">9</property>
-                        <property name="bottom_attach">10</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkAlignment" id="alignment10">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="xscale">0</property>
-                        <child>
-                          <object class="GtkEntry" id="entry6">
-                            <property name="visible">True</property>
-                            <property name="sensitive">False</property>
-                            <property name="can_focus">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">7</property>
-                        <property name="bottom_attach">8</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkRadioButton" id="radiobutton4">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                      </object>
-                      <packing>
-                        <property name="x_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkRadioButton" id="radiobutton6">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                        <property name="group">radiobutton4</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                        <property name="x_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkRadioButton" id="radiobutton7">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                        <property name="group">radiobutton4</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
-                        <property name="x_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkRadioButton" id="radiobutton8">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                        <property name="group">radiobutton4</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">4</property>
-                        <property name="bottom_attach">5</property>
-                        <property name="x_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkRadioButton" id="radiobutton10">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                        <property name="group">radiobutton4</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">6</property>
-                        <property name="bottom_attach">7</property>
-                        <property name="x_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkRadioButton" id="radiobutton5">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                        <property name="group">radiobutton4</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">8</property>
-                        <property name="bottom_attach">9</property>
-                        <property name="x_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label6">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">Value:</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label7">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">System Missing</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label8">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">System or User Missing</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkVBox" id="vbox2">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkAlignment" id="alignment9">
-                            <property name="visible">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="xalign">0</property>
-                            <property name="xscale">0</property>
-                            <child>
-                              <object class="GtkEntry" id="entry5">
-                                <property name="visible">True</property>
-                                <property name="sensitive">False</property>
-                                <property name="can_focus">True</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                              </object>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="label9">
-                            <property name="visible">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="xalign">0</property>
-                            <property name="label" translatable="yes">through</property>
-                          </object>
-                          <packing>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkAlignment" id="alignment7">
-                            <property name="visible">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="xalign">0</property>
-                            <property name="xscale">0</property>
-                            <child>
-                              <object class="GtkEntry" id="entry3">
-                                <property name="visible">True</property>
-                                <property name="sensitive">False</property>
-                                <property name="can_focus">True</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                              </object>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">5</property>
-                        <property name="bottom_attach">6</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label11">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">Range, LOWEST thru value</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">6</property>
-                        <property name="bottom_attach">7</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label12">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">Range, value thru HIGHEST</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">8</property>
-                        <property name="bottom_attach">9</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkRadioButton" id="radiobutton11">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                        <property name="group">radiobutton4</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">10</property>
-                        <property name="bottom_attach">11</property>
-                        <property name="x_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label13">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">All other values</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">10</property>
-                        <property name="bottom_attach">11</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkAlignment" id="alignment6">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="xscale">0</property>
-                        <child>
-                          <object class="GtkEntry" id="entry2">
-                            <property name="visible">True</property>
-                            <property name="sensitive">False</property>
-                            <property name="can_focus">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label10">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">Range:</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">4</property>
-                        <property name="bottom_attach">5</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-            <child type="label">
-              <object class="GtkLabel" id="label5">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">Old Value</property>
-                <property name="use_markup">True</property>
-              </object>
-            </child>
           </object>
           <packing>
             <property name="position">0</property>
index 7c454b79787831b11c72c1454da2cb27f0cc91e9..e56c095c1de562b6ed8976ebe292011af9fac25d 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <interface>
-  <!-- interface-requires gtk+ 2.12 -->
   <requires lib="psppire" version="2054.17080"/>
+  <!-- interface-requires gtk+ 2.12 -->
   <!-- interface-naming-policy project-wide -->
   <object class="PsppireDialog" id="regression-dialog">
     <property name="title" translatable="yes">Regression</property>
         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
         <property name="spacing">2</property>
         <child>
-          <object class="GtkTable" id="table1">
+          <object class="GtkAlignment" id="alignment1">
             <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="n_rows">3</property>
-            <property name="n_columns">3</property>
+            <property name="top_padding">5</property>
+            <property name="left_padding">5</property>
             <child>
-              <object class="GtkHButtonBox" id="hbuttonbox1">
+              <object class="GtkTable" id="table1">
                 <property name="visible">True</property>
                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="layout_style">spread</property>
+                <property name="n_rows">3</property>
+                <property name="n_columns">3</property>
+                <child>
+                  <object class="GtkHButtonBox" id="hbuttonbox1">
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="layout_style">spread</property>
+                    <child>
+                      <object class="GtkButton" id="stat-button">
+                        <property name="label" translatable="yes">S_tatistics...</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="use_underline">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="save-button">
+                        <property name="label" translatable="yes">_Save...</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="use_underline">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                    <property name="y_options"></property>
+                    <property name="y_padding">5</property>
+                  </packing>
+                </child>
                 <child>
-                  <object class="GtkButton" id="stat-button">
-                    <property name="label" translatable="yes">Statistics...</property>
+                  <object class="PsppireSelector" id="dep-selector">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
                     <property name="receives_default">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="no_show_all">True</property>
+                    <property name="border_width">5</property>
+                    <property name="source_widget">dict-view</property>
+                    <property name="dest_widget">dep-view</property>
                   </object>
                   <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">0</property>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="x_options"></property>
+                    <property name="y_options"></property>
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkButton" id="save-button">
-                    <property name="label" translatable="yes">Save...</property>
+                  <object class="PsppireSelector" id="indep-selector">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
                     <property name="receives_default">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="no_show_all">True</property>
+                    <property name="border_width">5</property>
+                    <property name="source_widget">dict-view</property>
+                    <property name="dest_widget">indep-view</property>
                   </object>
                   <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="x_options"></property>
+                    <property name="y_options"></property>
                   </packing>
                 </child>
-              </object>
-              <packing>
-                <property name="right_attach">3</property>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
-                <property name="y_options"></property>
-                <property name="y_padding">5</property>
-              </packing>
-            </child>
-            <child>
-              <object class="PsppireSelector" id="dep-selector">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="no_show_all">True</property>
-                <property name="border_width">5</property>
-                <property name="source_widget">dict-view</property>
-                <property name="dest_widget">dep-view</property>
-              </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="x_options"></property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <object class="PsppireSelector" id="indep-selector">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="no_show_all">True</property>
-                <property name="border_width">5</property>
-                <property name="source_widget">dict-view</property>
-                <property name="dest_widget">indep-view</property>
-              </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-                <property name="x_options"></property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkScrolledWindow" id="variables">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="hscrollbar_policy">never</property>
-                <property name="vscrollbar_policy">automatic</property>
-                <property name="shadow_type">etched-in</property>
                 <child>
-                  <object class="PsppireDictView" id="dict-view">
+                  <object class="GtkScrolledWindow" id="variables">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="headers_visible">False</property>
+                    <property name="hscrollbar_policy">never</property>
+                    <property name="vscrollbar_policy">automatic</property>
+                    <property name="shadow_type">etched-in</property>
+                    <child>
+                      <object class="PsppireDictView" id="dict-view">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="headers_visible">False</property>
+                        <property name="headers_clickable">False</property>
+                      </object>
+                    </child>
                   </object>
+                  <packing>
+                    <property name="bottom_attach">2</property>
+                  </packing>
                 </child>
-              </object>
-              <packing>
-                <property name="bottom_attach">2</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFrame" id="frame2">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label_xalign">0</property>
-                <property name="shadow_type">none</property>
                 <child>
-                  <object class="GtkAlignment" id="alignment1">
+                  <object class="GtkFrame" id="frame2">
                     <property name="visible">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="left_padding">12</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">none</property>
                     <child>
-                      <object class="GtkScrolledWindow" id="scrolledwindow1">
+                      <object class="GtkAlignment" id="alignment2">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="hscrollbar_policy">never</property>
-                        <property name="vscrollbar_policy">automatic</property>
-                        <property name="shadow_type">etched-in</property>
+                        <property name="left_padding">12</property>
                         <child>
-                          <object class="PsppireVarView" id="dep-view">
+                          <object class="GtkScrolledWindow" id="scrolledwindow1">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="headers_visible">False</property>
+                            <property name="hscrollbar_policy">never</property>
+                            <property name="vscrollbar_policy">automatic</property>
+                            <property name="shadow_type">etched-in</property>
+                            <child>
+                              <object class="PsppireVarView" id="dep-view">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="headers_visible">False</property>
+                                <property name="headers_clickable">False</property>
+                              </object>
+                            </child>
                           </object>
                         </child>
                       </object>
                     </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label1">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="label" translatable="yes">_Dependent</property>
+                        <property name="use_markup">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">dep-view</property>
+                      </object>
+                    </child>
                   </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                  </packing>
                 </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label1">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label" translatable="yes">Dependent</property>
-                    <property name="use_markup">True</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFrame" id="frame3">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label_xalign">0</property>
-                <property name="shadow_type">none</property>
                 <child>
-                  <object class="GtkAlignment" id="alignment2">
+                  <object class="GtkFrame" id="frame3">
                     <property name="visible">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="left_padding">12</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">none</property>
                     <child>
-                      <object class="GtkScrolledWindow" id="scrolledwindow2">
+                      <object class="GtkAlignment" id="alignment4">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="hscrollbar_policy">never</property>
-                        <property name="vscrollbar_policy">automatic</property>
-                        <property name="shadow_type">etched-in</property>
+                        <property name="left_padding">12</property>
                         <child>
-                          <object class="PsppireVarView" id="indep-view">
+                          <object class="GtkScrolledWindow" id="scrolledwindow2">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="headers_visible">False</property>
+                            <property name="hscrollbar_policy">never</property>
+                            <property name="vscrollbar_policy">automatic</property>
+                            <property name="shadow_type">etched-in</property>
+                            <child>
+                              <object class="PsppireVarView" id="indep-view">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="headers_visible">False</property>
+                                <property name="headers_clickable">False</property>
+                              </object>
+                            </child>
                           </object>
                         </child>
                       </object>
                     </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label3">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="label" translatable="yes">_Independent</property>
+                        <property name="use_markup">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">indep-view</property>
+                      </object>
+                    </child>
                   </object>
-                </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label3">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label" translatable="yes">Independent</property>
-                    <property name="use_markup">True</property>
-                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                  </packing>
                 </child>
               </object>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="right_attach">3</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-              </packing>
             </child>
           </object>
           <packing>
             <property name="visible">True</property>
             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
             <property name="orientation">vertical</property>
+            <property name="homogeneous">True</property>
             <child>
               <object class="GtkCheckButton" id="pred-button">
-                <property name="label" translatable="yes">Predicted values</property>
+                <property name="label" translatable="yes">_Predicted values</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">False</property>
                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="use_underline">True</property>
                 <property name="draw_indicator">True</property>
               </object>
               <packing>
             </child>
             <child>
               <object class="GtkCheckButton" id="resid-button">
-                <property name="label" translatable="yes">Residuals</property>
+                <property name="label" translatable="yes">_Residuals</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">False</property>
                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="use_underline">True</property>
                 <property name="draw_indicator">True</property>
               </object>
               <packing>
               <object class="GtkAlignment" id="alignment3">
                 <property name="visible">True</property>
                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="left_padding">12</property>
                 <child>
                   <object class="GtkScrolledWindow" id="scrolledwindow4">
                     <property name="visible">True</property>
               <object class="GtkLabel" id="label2">
                 <property name="visible">True</property>
                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">Statistics</property>
+                <property name="label" translatable="yes">S_tatistics</property>
                 <property name="use_markup">True</property>
+                <property name="use_underline">True</property>
+                <property name="mnemonic_widget">stat-view</property>
               </object>
             </child>
           </object>
index 96353509ed84918671b87de2a493bf187e314ad7..9593b80c9cc32d1a745cfa990cd298b976c2c7f1 100644 (file)
                                 <property name="label" translatable="yes">_Items:</property>
                                 <property name="use_markup">True</property>
                                 <property name="use_underline">True</property>
+                                <property name="mnemonic_widget">treeview2</property>
                               </object>
                             </child>
                           </object>
                               <object class="GtkLabel" id="label3">
                                 <property name="visible">True</property>
                                 <property name="xalign">1</property>
-                                <property name="label" translatable="yes">Model:       </property>
+                                <property name="label" translatable="yes">_Model: </property>
+                                <property name="use_underline">True</property>
                                 <property name="justify">right</property>
+                                <property name="mnemonic_widget">combobox1</property>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
                             <child>
                               <object class="GtkLabel" id="label2">
                                 <property name="visible">True</property>
-                                <property name="label" translatable="yes">Variables in first split:</property>
+                                <property name="label" translatable="yes">_Variables in first split:</property>
+                                <property name="use_underline">True</property>
+                                <property name="mnemonic_widget">spinbutton1</property>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
                 </child>
                 <child>
                   <object class="GtkCheckButton" id="totals-checkbutton">
-                    <property name="label" translatable="yes">Show descriptives for scale if _item is deleted</property>
-                    <property name="use_underline">True</property>
+                    <property name="label" translatable="yes">Show _descriptives for scale if item is deleted</property>
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
                     <property name="receives_default">False</property>
+                    <property name="use_underline">True</property>
                     <property name="draw_indicator">True</property>
                   </object>
                   <packing>
index 74bd8157ab7b72a16dc08e62ee47d5bc2846f38f..87f0c98addb600f5beb21f4f88eef82e5f8781a8 100644 (file)
                     <property name="label" translatable="yes">_Test Variable:</property>
                     <property name="use_markup">True</property>
                     <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">psppire-var-view1</property>
                   </object>
                 </child>
               </object>
                     <property name="label" translatable="yes">_State Variable:</property>
                     <property name="use_markup">True</property>
                     <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">entry1</property>
                   </object>
                 </child>
               </object>
diff --git a/src/ui/gui/runs-dialog.c b/src/ui/gui/runs-dialog.c
new file mode 100644 (file)
index 0000000..64f50ac
--- /dev/null
@@ -0,0 +1,223 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  Free Software Foundation
+
+   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 "dialog-common.h"
+#include <ui/syntax-gen.h>
+#include <libpspp/str.h>
+
+#include "runs-dialog.h"
+#include "psppire-selector.h"
+#include "psppire-dictview.h"
+#include "psppire-dialog.h"
+
+#include "psppire-data-window.h"
+#include "psppire-var-view.h"
+
+#include "executor.h"
+#include "helper.h"
+
+#include <gtk/gtk.h>
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+
+enum
+  {
+    CB_MEDIAN,
+    CB_MEAN,
+    CB_MODE,
+    CB_CUSTOM
+  };
+
+struct runs
+{
+  GtkBuilder *xml;
+  PsppireDict *dict;
+
+  GtkWidget *variables;
+  PsppireDataWindow *de ;
+
+  GtkWidget *entry;
+  GtkWidget *cb[4];
+};
+
+static char * generate_syntax (const struct runs *rd);
+
+/* Makes widget W's sensitivity follow the active state of TOGGLE */
+static void
+sensitive_if_active (GtkToggleButton *toggle, GtkWidget *w)
+{
+  gboolean active = gtk_toggle_button_get_active (toggle);
+
+  gtk_widget_set_sensitive (w, active);
+}
+
+static void
+refresh (struct runs *fd)
+{
+  int i;
+  GtkTreeModel *liststore =
+    gtk_tree_view_get_model (GTK_TREE_VIEW (fd->variables));
+  gtk_list_store_clear (GTK_LIST_STORE (liststore));
+
+  gtk_entry_set_text (GTK_ENTRY (fd->entry), "");
+
+  for (i = 0; i < 4; ++i)
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->cb[i]), FALSE);
+}
+
+
+static gboolean
+dialog_state_valid (gpointer data)
+{
+  int i;
+  struct runs *fd = data;
+
+  GtkTreeModel *liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (fd->variables));
+
+  if  (gtk_tree_model_iter_n_children (liststore, NULL) < 1)
+    return FALSE;
+
+  for (i = 0; i < 4; ++i)
+    {
+      if ( TRUE == gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->cb[i])))
+       break;
+    }
+  if ( i >= 4)
+    return FALSE;
+
+
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->cb[CB_CUSTOM])))
+    {
+      if (0 == strcmp ("", gtk_entry_get_text (GTK_ENTRY (fd->entry))))
+       return FALSE;
+    }
+
+  return TRUE;
+}
+
+
+/* Pops up the Runs dialog box */
+void
+runs_dialog (PsppireDataWindow *dw)
+{
+  struct runs fd;
+  gint response;
+
+  PsppireVarStore *vs;
+
+  GtkWidget *dialog ;
+  GtkWidget *source ;
+
+  fd.xml = builder_new ("runs.ui");
+
+  dialog = get_widget_assert   (fd.xml, "runs-dialog");
+  source = get_widget_assert   (fd.xml, "dict-view");
+
+  fd.entry = get_widget_assert   (fd.xml, "entry1");
+  fd.cb[CB_MEDIAN] = get_widget_assert (fd.xml, "checkbutton1");
+  fd.cb[CB_MEAN] = get_widget_assert (fd.xml, "checkbutton2");
+  fd.cb[CB_MODE] = get_widget_assert (fd.xml, "checkbutton4");
+  fd.cb[CB_CUSTOM] = get_widget_assert (fd.xml, "checkbutton3");
+
+  fd.de = dw;
+
+  g_signal_connect_swapped (dialog, "refresh", G_CALLBACK (refresh),  &fd);
+
+
+  fd.variables = get_widget_assert   (fd.xml, "psppire-var-view1");
+
+  g_object_get (fd.de->data_editor, "var-store", &vs, NULL);
+
+  gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (fd.de));
+
+  g_object_get (vs, "dictionary", &fd.dict, NULL);
+  g_object_set (source, "model", fd.dict,
+               "predicate", var_is_numeric,
+               NULL);
+
+  g_signal_connect (fd.cb[CB_CUSTOM], "toggled",
+                   G_CALLBACK (sensitive_if_active), fd.entry);
+
+  psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (dialog),
+                                     dialog_state_valid, &fd);
+
+  response = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
+
+  switch (response)
+    {
+    case GTK_RESPONSE_OK:
+      g_free (execute_syntax_string (dw, generate_syntax (&fd)));
+      break;
+    case PSPPIRE_RESPONSE_PASTE:
+      g_free (paste_syntax_to_window (generate_syntax (&fd)));
+      break;
+    default:
+      break;
+    }
+
+  g_object_unref (fd.xml);
+}
+
+
+\f
+static void
+append_fragment (GString *string, const gchar *cut, PsppireVarView *vv)
+{
+  g_string_append (string, "\n\t/RUNS");
+
+  g_string_append (string, " ( ");
+  g_string_append (string, cut);
+  g_string_append (string, " ) = ");
+
+  psppire_var_view_append_names (vv, 0, string);
+}
+
+
+char *
+generate_syntax (const struct runs *rd)
+{
+  gchar *text;
+
+  GString *string = g_string_new ("NPAR TEST");
+
+  if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->cb[CB_MEAN])))
+    append_fragment (string, "MEAN", PSPPIRE_VAR_VIEW (rd->variables));
+
+  if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->cb[CB_MEDIAN])))
+    append_fragment (string, "MEDIAN", PSPPIRE_VAR_VIEW (rd->variables));
+
+  if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->cb[CB_MODE])))
+    append_fragment (string, "MODE", PSPPIRE_VAR_VIEW (rd->variables));
+
+  if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->cb[CB_CUSTOM])))
+    {
+      char *text = gtk_entry_get_text (GTK_ENTRY (rd->entry));
+      append_fragment (string, text, PSPPIRE_VAR_VIEW (rd->variables));
+    }
+
+  g_string_append (string, ".\n");
+
+  text = string->str;
+
+  g_string_free (string, FALSE);
+
+  return text;
+}
diff --git a/src/ui/gui/runs-dialog.h b/src/ui/gui/runs-dialog.h
new file mode 100644 (file)
index 0000000..f34b48d
--- /dev/null
@@ -0,0 +1,24 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  Free Software Foundation
+
+   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/>. */
+
+#ifndef __RUNS_DIALOG_H
+#define __RUNS_DIALOG_H
+
+#include "psppire-data-window.h"
+
+void runs_dialog (PsppireDataWindow * data);
+
+#endif
diff --git a/src/ui/gui/runs.ui b/src/ui/gui/runs.ui
new file mode 100644 (file)
index 0000000..96c894a
--- /dev/null
@@ -0,0 +1,227 @@
+<?xml version="1.0"?>
+<interface>
+  <!-- interface-requires psppire 0.0 -->
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="PsppireDialog" id="runs-dialog">
+    <property name="title" translatable="yes">Runs Test</property>
+    <property name="modal">True</property>
+    <property name="orientation">Vertical</property>
+    <child internal-child="hbox">
+      <object class="GtkVBox" id="dialog-hbox1">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child>
+          <object class="GtkAlignment" id="alignment1">
+            <property name="visible">True</property>
+            <property name="top_padding">5</property>
+            <property name="left_padding">5</property>
+            <property name="right_padding">5</property>
+            <child>
+              <object class="GtkVBox" id="vbox1">
+                <property name="visible">True</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">5</property>
+                <child>
+                  <object class="GtkHBox" id="hbox1">
+                    <property name="visible">True</property>
+                    <child>
+                      <object class="GtkScrolledWindow" id="scrolledwindow1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="hscrollbar_policy">never</property>
+                        <property name="vscrollbar_policy">automatic</property>
+                        <property name="shadow_type">in</property>
+                        <child>
+                          <object class="PsppireDictView" id="dict-view">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="border_width">5</property>
+                            <property name="headers_visible">False</property>
+                            <property name="headers_clickable">False</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkAlignment" id="alignment3">
+                        <property name="visible">True</property>
+                        <property name="xscale">0</property>
+                        <property name="yscale">0</property>
+                        <child>
+                          <object class="PsppireSelector" id="psppire-selector1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="border_width">5</property>
+                            <property name="source_widget">dict-view</property>
+                            <property name="dest_widget">psppire-var-view1</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkScrolledWindow" id="scrolledwindow2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="hscrollbar_policy">never</property>
+                        <property name="vscrollbar_policy">automatic</property>
+                        <property name="shadow_type">in</property>
+                        <child>
+                          <object class="PsppireVarView" id="psppire-var-view1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="border_width">5</property>
+                            <property name="headers_visible">False</property>
+                            <property name="headers_clickable">False</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkFrame" id="frame1">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <child>
+                      <object class="GtkAlignment" id="alignment2">
+                        <property name="visible">True</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <object class="GtkTable" id="table1">
+                            <property name="visible">True</property>
+                            <property name="n_rows">2</property>
+                            <property name="n_columns">2</property>
+                            <child>
+                              <object class="GtkCheckButton" id="checkbutton1">
+                                <property name="label" translatable="yes">_Median</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="checkbutton2">
+                                <property name="label" translatable="yes">M_ean</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="checkbutton4">
+                                <property name="label" translatable="yes">Mo_de</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_underline">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkHBox" id="hbox2">
+                                <property name="visible">True</property>
+                                <child>
+                                  <object class="GtkCheckButton" id="checkbutton3">
+                                    <property name="label" translatable="yes">_Custom:</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">False</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="draw_indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkEntry" id="entry1">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="invisible_char">&#x25CF;</property>
+                                    <property name="width_chars">0</property>
+                                  </object>
+                                  <packing>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label1">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Cut Point</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="PsppireHButtonBox" id="psppire-hbuttonbox1">
+            <property name="visible">True</property>
+            <property name="border_width">5</property>
+            <property name="default">PSPPIRE_BUTTON_GOTO_MASK</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
index 381fc3dd8a104649404358b1abb5a7f4a7f08735..9febcafaaa252dbb69ff950984c79640e9fcc078 100644 (file)
@@ -25,6 +25,7 @@
 #include "dict-display.h"
 #include "dialog-common.h"
 #include "widget-io.h"
+#include "psppire-scanf.h"
 #include "helper.h"
 #include <xalloc.h>
 
@@ -103,7 +104,7 @@ sample_subdialog (GtkButton *b, gpointer data)
 
   if ( ! scd->hbox1 )
     {
-      scd->hbox1 = widget_scanf (gettext (label1), &scd->spinbutton);
+      scd->hbox1 = psppire_scanf_new (gettext (label1), &scd->spinbutton);
 
       gtk_widget_show (scd->hbox1);
 
@@ -120,7 +121,7 @@ sample_subdialog (GtkButton *b, gpointer data)
   if ( ! scd->hbox2 )
     {
       scd->hbox2 =
-       widget_scanf (gettext (label2), &scd->spinbutton1, &scd->spinbutton2);
+       psppire_scanf_new (gettext (label2), &scd->spinbutton1, &scd->spinbutton2);
 
       gtk_spin_button_set_range (GTK_SPIN_BUTTON (scd->spinbutton1),
                                 1, case_count);
index 8983bc6741917825884944d77967d31516064d89..d4adf587d1c3858b6531bfecf9596d05d5e5baba 100644 (file)
@@ -416,7 +416,7 @@ t_test_independent_samples_dialog (PsppireDataWindow *de)
 
   tt_d.define_groups_button = get_widget_assert (xml, "define-groups-button");
   tt_d.groups_entry = get_widget_assert (xml, "indep-samples-t-test-entry");
-  tt_d.opts = tt_options_dialog_create (xml, GTK_WINDOW (de));
+  tt_d.opts = tt_options_dialog_create (GTK_WINDOW (de));
   tt_d.grps = tt_groups_dialog_create (xml, GTK_WINDOW (de));
 
 
index befe868204a156e67ed7f7e9ca71414b26d910a1..477d1de5156a163bbf450a5d85f33d6e2ee50f99 100644 (file)
@@ -141,7 +141,7 @@ t_test_one_sample_dialog (PsppireDataWindow *de)
   g_object_get (vs, "dictionary", &tt_d.dict, NULL);
   tt_d.vars_treeview = get_widget_assert (xml, "one-sample-t-test-treeview1");
   tt_d.test_value_entry = get_widget_assert (xml, "test-value-entry");
-  tt_d.opt = tt_options_dialog_create (xml, GTK_WINDOW (de));
+  tt_d.opt = tt_options_dialog_create (GTK_WINDOW (de));
 
   gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (de));
 
index 224b022caa670cc5d52710af4f2ae562d92e9031..d4656bf4a457bc811a08219df7624e32ce610ca1 100644 (file)
@@ -25,6 +25,7 @@
 #include "t-test-options.h"
 
 #include "widget-io.h"
+#include "psppire-scanf.h"
 
 #include <gettext.h>
 #define _(msgid) gettext (msgid)
@@ -49,23 +50,25 @@ struct tt_options_dialog
   gdouble confidence_interval;
   gboolean non_default_options;
   enum exclude_mode excl;
+  GtkBuilder *xml;
 };
 
 struct tt_options_dialog *
-tt_options_dialog_create (GtkBuilder *xml, GtkWindow *parent)
+tt_options_dialog_create (GtkWindow *parent)
 {
   struct tt_options_dialog *tto = xmalloc (sizeof (*tto));
 
+  tto->xml = builder_new ("t-test.ui");
+
   tto->confidence =
-    widget_scanf (_("Confidence Interval: %2d %%"),
-                 &tto->conf_percent);
+    psppire_scanf_new (_("Confidence Interval: %2d %%"), &tto->conf_percent);
 
-  tto->dialog = get_widget_assert (xml, "options-dialog");
+  tto->dialog = get_widget_assert (tto->xml, "options-dialog");
 
-  tto->box =   get_widget_assert (xml, "vbox1");
+  tto->box =   get_widget_assert (tto->xml, "vbox1");
 
-  tto->analysis = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "radiobutton1"));
-  tto->listwise = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "radiobutton2"));
+  tto->analysis = GTK_TOGGLE_BUTTON (get_widget_assert (tto->xml, "radiobutton1"));
+  tto->listwise = GTK_TOGGLE_BUTTON (get_widget_assert (tto->xml, "radiobutton2"));
 
   gtk_widget_show (tto->confidence);
 
@@ -84,6 +87,7 @@ void
 tt_options_dialog_destroy (struct tt_options_dialog *tto)
 {
   gtk_container_remove (GTK_CONTAINER (tto->box), tto->confidence);
+  g_object_unref (tto->xml);
   g_free (tto);
 }
 
@@ -115,7 +119,7 @@ tt_options_dialog_run (struct tt_options_dialog *tto)
 }
 
 void
-tt_options_dialog_append_syntax (struct tt_options_dialog *tto, GString *str)
+tt_options_dialog_append_syntax (const struct tt_options_dialog *tto, GString *str)
 {
   g_string_append (str, "\t/MISSING=");
 
index e80ef44496c5e21e08e0eabd1cafc90a047694ef..4f138327f9273635140875c1e46f5a9857c443e9 100644 (file)
@@ -24,12 +24,12 @@ struct tt_options_dialog;
 
 void tt_options_dialog_run (struct tt_options_dialog *);
 
-struct tt_options_dialog * tt_options_dialog_create (GtkBuilder *, GtkWindow *);
+struct tt_options_dialog * tt_options_dialog_create (GtkWindow *);
 
 void tt_options_dialog_destroy (struct tt_options_dialog *);
 
 
-void tt_options_dialog_append_syntax (struct tt_options_dialog *, GString *);
+void tt_options_dialog_append_syntax (const struct tt_options_dialog *, GString *);
 
 
 #endif
index 6233aa30263cefd6c8bc30e3f51e999f4c813f19..212691d39b4c242f5158e40d4d3727d5018e1882 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPPIRE - a graphical user interface for PSPP.
-   Copyright (C) 2008, 2010, 2011  Free Software Foundation
+   Copyright (C) 2011  Free Software Foundation
 
    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
 #include <config.h>
 #include <gtk/gtk.h>
 
+#include "t-test-options.h"
+#include "t-test-paired-samples.h"
+
 #include "psppire-data-window.h"
 #include "psppire-selector.h"
 #include "psppire-var-view.h"
 
 #include "psppire-dict.h"
 #include "psppire-var-store.h"
-#include "t-test-paired-samples.h"
-#include "t-test-options.h"
 
 #include "dialog-common.h"
 #include "psppire-dialog.h"
 
 #include "psppire-var-ptr.h"
 
+#include "paired-dialog.h"
 
 #include <gettext.h>
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
 
 
-struct tt_paired_samples_dialog
+static void
+refresh (void *aux)
+{
+}
+
+
+static gboolean
+valid (void *aux)
 {
-  PsppireDict *dict;
-  GtkWidget *pairs_treeview;
-  GtkTreeModel *list_store;
-  struct tt_options_dialog *opt;
-};
+  return TRUE;
+}
 
 static gchar *
-generate_syntax (const struct tt_paired_samples_dialog *d)
+generate_syntax (const struct paired_samples_dialog *d, const struct tt_options_dialog *opt)
 {
   gchar *text = NULL;
   GString *str =   g_string_new ("T-TEST \n\tPAIRS = ");
@@ -65,7 +71,7 @@ generate_syntax (const struct tt_paired_samples_dialog *d)
   g_string_append (str, " (PAIRED)");
   g_string_append (str, "\n");
 
-  tt_options_dialog_append_syntax (d->opt, str);
+  tt_options_dialog_append_syntax (opt, str);
 
   g_string_append (str, ".\n");
 
@@ -75,153 +81,43 @@ generate_syntax (const struct tt_paired_samples_dialog *d)
   return text;
 }
 
-static void
-refresh (struct tt_paired_samples_dialog *tt_d)
-{
-  gtk_list_store_clear (GTK_LIST_STORE (tt_d->list_store));
-}
-
-static gboolean
-dialog_state_valid (gpointer data)
-{
-  struct variable *v = NULL;
-  struct tt_paired_samples_dialog *tt_d = data;
-  GtkTreeIter dest_iter;
-
-  gint n_rows = gtk_tree_model_iter_n_children  (tt_d->list_store, NULL);
-
-  if ( n_rows == 0 )
-    return FALSE;
-
-  /* Get the last row */
-  gtk_tree_model_iter_nth_child (tt_d->list_store, &dest_iter,
-                                NULL, n_rows - 1);
-
-  /* Get the last (2nd) column */
-  gtk_tree_model_get (tt_d->list_store, &dest_iter, 1, &v, -1);
-
-
-  return (v != NULL);
-}
-
-
-
-static void
-select_as_pair_member (GtkTreeIter source_iter,
-                      GtkWidget *dest,
-                      GtkTreeModel *source_model,
-                      gpointer data)
-{
-  struct variable *v;
-  struct variable *v1;
-  gint n_rows;
-  GtkTreeIter dest_iter;
-  struct tt_paired_samples_dialog *tt_d = data;
-
-
-  gtk_tree_model_get (source_model, &source_iter,
-                     DICT_TVM_COL_VAR, &v, -1);
-
-  n_rows = gtk_tree_model_iter_n_children  (tt_d->list_store, NULL);
-
-  if ( n_rows > 0 )
-    {
-
-      gtk_tree_model_iter_nth_child (tt_d->list_store,
-                                    &dest_iter, NULL, n_rows - 1);
-
-      gtk_tree_model_get (tt_d->list_store, &dest_iter, 1, &v1, -1);
-    }
-  else
-    v1 = NULL;
-
-  if ( n_rows == 0 || v1 != NULL)
-    {
-      gtk_list_store_append (GTK_LIST_STORE (tt_d->list_store), &dest_iter);
-
-      gtk_list_store_set (GTK_LIST_STORE (tt_d->list_store), &dest_iter,
-                         0, v,
-                         1, NULL,
-                         -1);
-    }
-  else
-    {
-      gtk_list_store_set (GTK_LIST_STORE (tt_d->list_store), &dest_iter,
-                         1, v,
-                         -1);
-
-    }
-}
-
 /* Pops up the dialog box */
 void
 t_test_paired_samples_dialog (PsppireDataWindow *de)
 {
-  struct tt_paired_samples_dialog tt_d;
   gint response;
+  struct paired_samples_dialog *tt_d = two_sample_dialog_create (de);
+  struct tt_options_dialog *opts = tt_options_dialog_create (GTK_WINDOW (de));
 
-  PsppireVarStore *vs = NULL;
-
-  GtkBuilder *xml = builder_new ("t-test.ui");
-
-  GtkWidget *dict_view =
-    get_widget_assert (xml, "paired-samples-t-test-treeview1");
-
-  GtkWidget *options_button = get_widget_assert (xml, "paired-samples-t-test-options-button");
-
-  GtkWidget *selector = get_widget_assert (xml, "psppire-selector3");
-
-  GtkWidget *dialog = get_widget_assert (xml, "t-test-paired-samples-dialog");
-
-  g_object_get (de->data_editor, "var-store", &vs, NULL);
-
-  g_object_get (vs, "dictionary", &tt_d.dict, NULL);
-  tt_d.pairs_treeview =
-   get_widget_assert (xml, "paired-samples-t-test-treeview2");
-  tt_d.opt = tt_options_dialog_create (xml, GTK_WINDOW (de));
-
-  gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (de));
-
-
-  g_object_set (dict_view, "model", tt_d.dict,
-               "predicate",
-               var_is_numeric, NULL);
+  GtkWidget *bb = gtk_hbutton_box_new ();
+  GtkWidget *opt = gtk_button_new_with_mnemonic (_("_Options"));
+  gtk_box_pack_start (GTK_BOX (bb), opt, TRUE, TRUE, 5);
 
+  gtk_widget_show_all (bb);
+  two_sample_dialog_add_widget (tt_d, bb);
   
-  tt_d.list_store = gtk_tree_view_get_model (GTK_TREE_VIEW (tt_d.pairs_treeview));
-
-  psppire_selector_set_select_func (PSPPIRE_SELECTOR (selector),
-                                   select_as_pair_member,
-                                   &tt_d);
-
-  g_signal_connect_swapped (dialog, "refresh",
-                           G_CALLBACK (refresh),  &tt_d);
-
+  g_signal_connect_swapped (opt, "clicked", G_CALLBACK (tt_options_dialog_run), opts);
 
-  g_signal_connect_swapped (options_button, "clicked",
-                           G_CALLBACK (tt_options_dialog_run), tt_d.opt);
+  tt_d->refresh = refresh;
+  tt_d->valid = valid;
+  tt_d->aux = opts;
 
-  psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (dialog),
-                                     dialog_state_valid, &tt_d);
+  gtk_window_set_title (GTK_WINDOW (tt_d->dialog), _("Paired Samples T Test"));
 
-  response = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
+  response = psppire_dialog_run (PSPPIRE_DIALOG (tt_d->dialog));
 
   switch (response)
     {
     case GTK_RESPONSE_OK:
-      g_free (execute_syntax_string (de, generate_syntax (&tt_d)));
+      g_free (execute_syntax_string (de, generate_syntax (tt_d, opts)));
       break;
     case PSPPIRE_RESPONSE_PASTE:
-      g_free (paste_syntax_to_window (generate_syntax (&tt_d)));
+      g_free (paste_syntax_to_window (generate_syntax (tt_d, opts)));
       break;
     default:
       break;
     }
 
-
-  g_object_unref (xml);
-
-  tt_options_dialog_destroy (tt_d.opt);
+  two_sample_dialog_destroy (tt_d);
+  tt_options_dialog_destroy (opts);
 }
-
-
index 1a763ae3bc33bec29744f9ea48d3bf2c523780b9..eb115d3d95d47967f1ca847966ae107a5f0c59c7 100644 (file)
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                     <property name="label" translatable="yes">Group_2 value:</property>
                     <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">group2-entry</property>
                   </object>
                   <packing>
                     <property name="top_attach">1</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                     <property name="label" translatable="yes">Group_1 value:</property>
                     <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">group1-entry</property>
                   </object>
                   <packing>
                     <property name="x_options"></property>
                     <property name="xalign">0</property>
                     <property name="label" translatable="yes">_Cut point:</property>
                     <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">radiobutton4</property>
                   </object>
                   <packing>
                     <property name="position">0</property>
                 <property name="xalign">0</property>
                 <property name="label" translatable="yes">_Use specified values:</property>
                 <property name="use_underline">True</property>
+                <property name="mnemonic_widget">radiobutton3</property>
               </object>
               <packing>
                 <property name="left_attach">1</property>
                 <property name="visible">True</property>
                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                 <property name="xalign">0</property>
-                <property name="label" translatable="yes">Test Value: </property>
+                <property name="label" translatable="yes">Test _Value: </property>
+                <property name="use_underline">True</property>
+                <property name="mnemonic_widget">test-value-entry</property>
               </object>
               <packing>
                 <property name="expand">False</property>
       </object>
     </child>
   </object>
-  <object class="PsppireDialog" id="t-test-paired-samples-dialog">
-    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-    <property name="title" translatable="yes">Paired Samples T Test</property>
-    <property name="modal">True</property>
-    <child internal-child="hbox">
-      <object class="GtkHBox" id="dialog-hbox6">
-        <property name="visible">True</property>
-        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-        <property name="spacing">2</property>
-        <child>
-          <object class="GtkHBox" id="hbox3">
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <child>
-              <object class="GtkScrolledWindow" id="scrolledwindow2">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="hscrollbar_policy">never</property>
-                <property name="vscrollbar_policy">automatic</property>
-                <property name="shadow_type">etched-in</property>
-                <child>
-                  <object class="PsppireDictView" id="paired-samples-t-test-treeview1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="headers_visible">False</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkAlignment" id="alignment5">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="yalign">0.059999998658895493</property>
-                <property name="yscale">0</property>
-                <child>
-                  <object class="PsppireSelector" id="psppire-selector3">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="no_show_all">True</property>
-                    <property name="border_width">5</property>
-                    <property name="source_widget">paired-samples-t-test-treeview1</property>
-                    <property name="dest_widget">paired-samples-t-test-treeview2</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkVBox" id="vbox3">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="orientation">vertical</property>
-                <property name="spacing">5</property>
-                <child>
-                  <object class="GtkFrame" id="frame4">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label_xalign">0</property>
-                    <property name="shadow_type">none</property>
-                    <child>
-                      <object class="GtkAlignment" id="alignment6">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="left_padding">12</property>
-                        <child>
-                          <object class="GtkScrolledWindow" id="scrolledwindow1">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="hscrollbar_policy">always</property>
-                            <property name="vscrollbar_policy">automatic</property>
-                            <property name="shadow_type">etched-in</property>
-                            <child>
-                              <object class="PsppireVarView" id="paired-samples-t-test-treeview2">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="enable_search">False</property>
-                                <property name="n-cols">2</property>
-                              </object>
-                            </child>
-                          </object>
-                        </child>
-                      </object>
-                    </child>
-                    <child type="label">
-                      <object class="GtkLabel" id="label13">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="label" translatable="yes">Test Variable(s):</property>
-                        <property name="use_markup">True</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkVButtonBox" id="vbuttonbox2">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="orientation">vertical</property>
-                    <child>
-                      <object class="GtkButton" id="paired-samples-t-test-options-button">
-                        <property name="label" translatable="yes">Options...</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="PsppireVButtonBox" id="psppire-vbuttonbox4">
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="border_width">5</property>
-            <property name="orientation">vertical</property>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="pack_type">end</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-  </object>
 </interface>
index 215a444c4861ba2d5d2faa0117b0608158af982a..09daa0e6b39a7ea8a033dd5d1b66bdd2e444585f 100644 (file)
@@ -43,7 +43,7 @@
 #include "ui/gui/psppire-dialog.h"
 #include "ui/gui/psppire-var-sheet.h"
 #include "ui/gui/psppire-var-store.h"
-#include "ui/gui/widget-io.h"
+#include "ui/gui/psppire-scanf.h"
 #include "ui/syntax-gen.h"
 
 #include "gl/error.h"
@@ -525,16 +525,17 @@ destroy_file (struct import_assistant *ia)
 static char *
 choose_file (GtkWindow *parent_window)
 {
-  GtkWidget *dialog;
   char *file_name;
 
-  dialog = gtk_file_chooser_dialog_new (_("Import Delimited Text Data"),
+  GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Import Delimited Text Data"),
                                         parent_window,
                                         GTK_FILE_CHOOSER_ACTION_OPEN,
                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                         GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                                         NULL);
 
+  g_object_set (dialog, "local-only", FALSE, NULL);
+
   switch (gtk_dialog_run (GTK_DIALOG (dialog)))
     {
     case GTK_RESPONSE_ACCEPT:
@@ -728,7 +729,7 @@ init_intro_page (struct import_assistant *ia)
 
   p->n_cases_spin = gtk_spin_button_new_with_range (0, INT_MAX, 100);
 
-  hbox_n_cases = widget_scanf (_("Only the first %4d cases"), &p->n_cases_spin);
+  hbox_n_cases = psppire_scanf_new (_("Only the first %4d cases"), &p->n_cases_spin);
 
   table  = get_widget_assert (builder, "button-table");
 
@@ -738,7 +739,7 @@ init_intro_page (struct import_assistant *ia)
 
   p->percent_spin = gtk_spin_button_new_with_range (0, 100, 10);
 
-  hbox_percent = widget_scanf (_("Only the first %3d %% of file (approximately)"), &p->percent_spin);
+  hbox_percent = psppire_scanf_new (_("Only the first %3d %% of file (approximately)"), &p->percent_spin);
 
   gtk_table_attach_defaults (GTK_TABLE (table), hbox_percent,
                             1, 2,
index fdc817184fe8bfd40e63504aef8ea2f1ed28e4dd..df64a1290e2e259af6928ab34c74d5ad5f1db21b 100644 (file)
   </object>
   <object class="GtkWindow" id="val_labs_dialog">
     <property name="title" translatable="yes">Value Labels</property>
-    <property name="resizable">False</property>
     <property name="modal">True</property>
     <property name="type_hint">dialog</property>
     <property name="skip_taskbar_hint">True</property>
                         <property name="right_attach">2</property>
                         <property name="top_attach">1</property>
                         <property name="bottom_attach">2</property>
-                        <property name="x_options">GTK_FILL</property>
                         <property name="y_options">GTK_FILL</property>
                       </packing>
                     </child>
                       <object class="GtkVButtonBox" id="vbuttonbox2">
                         <property name="visible">True</property>
                         <property name="border_width">5</property>
+                        <property name="orientation">vertical</property>
                         <child>
                           <object class="GtkButton" id="val_labs_add">
                             <property name="label">gtk-add</property>
           <object class="GtkVButtonBox" id="vbuttonbox3">
             <property name="visible">True</property>
             <property name="border_width">5</property>
+            <property name="orientation">vertical</property>
             <property name="spacing">5</property>
             <property name="layout_style">start</property>
             <child>
index 73a7301662033e366a1d8180692c131646b82aac..e04e32222d85cdc50f4052463f44191ffc8f2824 100644 (file)
 
 #include "xalloc.h"
 
-/* Create a GtkLabel and pack it into BOX.
-   The label is created using part of the string at S, and the directives
-   at DIRS[DIR_IDX] and subsequent.
-
-   After this function returns, *S points to the first unused character.
-*/
-static void
-ship_label (GtkBox *box, const char **s,
-           const char_directives *dirs, size_t dir_idx)
-{
-  GtkWidget *label ;
-  GString *str = g_string_new (*s);
-
-  if ( dirs)
-    {
-      char_directive dir = dirs->dir[dir_idx];
-      int n = 0;
-
-      while (dir_idx < dirs->count && dir.conversion == '%' )
-       {
-         g_string_erase (str, dir.dir_start - *s, 1);
-         dir = dirs->dir[++dir_idx];
-         n++;
-       }
-
-      g_string_truncate (str, dir.dir_start - *s - n);
-
-      if ( dir_idx >= dirs->count)
-       *s = NULL;
-      else
-       *s = dir.dir_end;
-    }
-
-  label = gtk_label_new (str->str);
-
-  g_string_free (str, TRUE);
-
-  gtk_box_pack_start (box, label, FALSE, FALSE, 0);
-  gtk_widget_show (label);
-}
 
 /* Returns a string generated from FMT and a list of GtkEntry widgets.
    Each conversion in FMT will be replaced with the text from the
@@ -139,104 +99,3 @@ widget_printf (const gchar *fmt, ...)
   g_string_free (output, FALSE);
   return text;
 }
-
-/*
-   Returns a GtkHBox populated with an GtkLabel and GtkEntry widgets.
-   Each conversion in FMT will cause a GtkEntry (possibly a GtkSpinButton) to
-   be created.  Any text between conversions produces a GtkLabel.
-   There should be N arguments following FMT should be of type GtkEntry **,
-   where N is the number of conversions.
-   These arguments will be filled with a pointer to the corresponding widgets.
-   Their properties may be changed, but they should not be unrefed.
- */
-GtkWidget *
-widget_scanf (const gchar *fmt, ...)
-{
-  char_directives d;
-  arguments a;
-  int i;
-  va_list ap;
-  GtkWidget ***widgets = NULL;
-  GtkWidget *hbox = NULL;
-  GtkWidget **w;
-  const char *s = fmt;
-
-  if ( 0 !=  printf_parse (fmt, &d, &a) )
-    return NULL;
-
-  if (a.arg != a.direct_alloc_arg)
-    free (a.arg);
-
-  va_start (ap, fmt);
-
-  if ( d.count > 0 )
-    {
-      hbox = gtk_hbox_new (FALSE, 0);
-      widgets = calloc (sizeof (*widgets), d.count);
-    }
-
-  for (i = 0 ; i < d.count ; ++i )
-    {
-      if ( d.dir[i].conversion != '%')
-       widgets[i] = va_arg (ap, GtkWidget **);
-    }
-  va_end (ap);
-
-
-
-  for (i = 0 ; i < d.count ; ++i )
-    {
-      char_directive dir = d.dir[i];
-      int precision = 0;
-      int width = 0;
-
-
-      if ( dir.precision_start && dir.precision_end)
-       precision = strtol (dir.precision_start + 1,
-                           (char **) &dir.precision_end, 10);
-
-      if ( dir.width_start && dir.width_end )
-       width = strtol (dir.width_start, (char **) &dir.width_end, 10);
-
-      if ( dir.dir_start > s )
-       ship_label (GTK_BOX (hbox), &s, &d, i);
-
-      if ( dir.conversion == '%')
-       {
-         if (s) s++;
-         continue;
-       }
-
-      w = widgets [dir.arg_index];
-      switch (dir.conversion)
-       {
-       case 'd':
-       case 'i':
-       case 'f':
-         {
-           *w = gtk_spin_button_new_with_range (0, 100.0, 1.0);
-           g_object_set (*w, "digits", precision, NULL);
-         }
-         break;
-       case 's':
-         *w = gtk_entry_new ();
-         break;
-       };
-
-      g_object_set (*w, "width-chars", width, NULL);
-      gtk_box_pack_start (GTK_BOX (hbox), *w, FALSE, FALSE, 0);
-      gtk_widget_show (*w);
-    }
-
-  if ( s && *s )
-    ship_label (GTK_BOX (hbox), &s, NULL, 0);
-
-
-
-  g_free (widgets);
-
-  if (d.dir != d.direct_alloc_dir)
-    free (d.dir);
-
-  return hbox;
-}
index 0fdb8caae7941557cddb22c4fd3d732d48f484ee..ee708f5426592d7337bd552d45b59da5d75a4635 100644 (file)
    The returned string should be freed when no longer required.
  */
 gchar * widget_printf (const gchar *fmt, ...);
-
-/*
-   Returns a GtkHBox populated with an GtkLabel and GtkEntry widgets.
-   Each conversion in FMT will cause a GtkEntry (possibly a GtkSpinButton) to
-   be created.  Any text between conversions produces a GtkLabel.
-   There should be N arguments following FMT should be of type GtkEntry **,
-   where N is the number of conversions.
-   These arguments will be filled with a pointer to the corresponding widgets.
-   Their properties may be changed, but they should not be unrefed.
- */
-GtkWidget *widget_scanf (const gchar *fmt, ...);
index a1a55d1453a3816bd1a3bdf68c7b0b833bf3bccc..9a634f73f333d005425f630d4283ea946ef587f3 100644 (file)
@@ -11,6 +11,7 @@
 #include "psppire-acr.h"
 #include "psppire-dictview.h"
 #include "psppire-var-view.h"
+#include "psppire-val-chooser.h"
 
 
 /* Any custom widgets which are to be used in GtkBuilder ui files
@@ -19,6 +20,7 @@
 void
 preregister_widgets (void)
 {
+  psppire_val_chooser_get_type ();
   psppire_dialog_get_type ();
   psppire_selector_get_type ();
   psppire_vbutton_box_get_type ();
index 7c80d27b39df747579f6ba1e20599e8db9757c81..db561a9a2fde0b7e26452579eec8525cc32f43e9 100644 (file)
@@ -153,6 +153,36 @@ terminal_reader_create (void)
   return &r->reader;
 }
 \f
+
+
+static const char *
+readline_prompt (enum prompt_style style)
+{
+  switch (style)
+    {
+    case PROMPT_FIRST:
+      return "PSPP> ";
+
+    case PROMPT_LATER:
+      return "    > ";
+
+    case PROMPT_DATA:
+      return "data> ";
+
+    case PROMPT_COMMENT:
+      return "comment> ";
+
+    case PROMPT_DOCUMENT:
+      return "document> ";
+
+    case PROMPT_DO_REPEAT:
+      return "DO REPEAT> ";
+    }
+
+  NOT_REACHED ();
+}
+
+
 #if HAVE_READLINE
 #include <readline/readline.h>
 #include <readline/history.h>
@@ -189,33 +219,6 @@ readline_done (void)
   free (history_file);
 }
 
-static const char *
-readline_prompt (enum prompt_style style)
-{
-  switch (style)
-    {
-    case PROMPT_FIRST:
-      return "PSPP> ";
-
-    case PROMPT_LATER:
-      return "    > ";
-
-    case PROMPT_DATA:
-      return "data> ";
-
-    case PROMPT_COMMENT:
-      return "comment> ";
-
-    case PROMPT_DOCUMENT:
-      return "document> ";
-
-    case PROMPT_DO_REPEAT:
-      return "DO REPEAT> ";
-    }
-
-  NOT_REACHED ();
-}
-
 static struct substring
 readline_read (enum prompt_style style)
 {
@@ -295,7 +298,7 @@ readline_done (void)
 static struct substring
 readline_read (enum prompt_style style)
 {
-  const char *prompt = prompt_get (style);
+  const char *prompt = readline_prompt (style);
   struct string line;
 
   fputs (prompt, stdout);
index 9b54a705b4755cbda91b9f46ddce34b1e589a62b..cfe019a238d4e2d7ee400b28c9d3ef7a0b198a43 100644 (file)
@@ -3,6 +3,7 @@
 # Variables used internally by the testsuite.
 EXEEXT='@EXEEXT@'
 GNM_SUPPORT='@GNM_SUPPORT@'
+ODF_READ_SUPPORT='@ODF_READ_SUPPORT@'
 PERL='@PERL@'
 WITH_PERL_MODULE='@WITH_PERL_MODULE@'
 host='@host@'
index 61c7996fb9501097d1eca7fcff43c966d3778bf7..1614f059aeaaf2af001681a5c108b9a9a47dc53e 100644 (file)
@@ -27,6 +27,7 @@ check_PROGRAMS += \
        tests/libpspp/stringi-set-test \
        tests/libpspp/tower-test \
        tests/libpspp/u8-istream-test \
+       tests/libpspp/zip-test \
        tests/output/render-test
 
 check-programs: $(check_PROGRAMS)
@@ -57,11 +58,9 @@ tests_libpspp_encoding_guesser_test_SOURCES = \
 tests_libpspp_encoding_guesser_test_LDADD = src/libpspp/libpspp.la gl/libgl.la
 
 tests_libpspp_heap_test_SOURCES = \
-       src/libpspp/heap.c \
-       src/libpspp/pool.c \
-       src/libpspp/temp-file.c \
        tests/libpspp/heap-test.c
 tests_libpspp_heap_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10
+tests_libpspp_heap_test_LDADD = src/libpspp/libpspp.la gl/libgl.la
 
 tests_libpspp_hmap_test_SOURCES = \
        src/libpspp/hmap.c \
@@ -94,36 +93,23 @@ tests_libpspp_range_map_test_SOURCES = \
 tests_libpspp_range_map_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10
 
 tests_libpspp_range_set_test_SOURCES = \
-       src/libpspp/bt.c \
-       src/libpspp/pool.c \
-       src/libpspp/range-set.c \
-       src/libpspp/temp-file.c \
        tests/libpspp/range-set-test.c
 tests_libpspp_range_set_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10
+tests_libpspp_range_set_test_LDADD = src/libpspp/libpspp.la gl/libgl.la
 
 tests_libpspp_str_test_SOURCES = \
        tests/libpspp/str-test.c
 tests_libpspp_str_test_LDADD = src/libpspp/libpspp.la gl/libgl.la 
 
 tests_libpspp_string_map_test_SOURCES = \
-       src/libpspp/hash-functions.c \
-       src/libpspp/hmap.c \
-       src/libpspp/string-map.c \
-       src/libpspp/string-set.c \
        tests/libpspp/string-map-test.c
 tests_libpspp_string_map_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10
+tests_libpspp_string_map_test_LDADD = src/libpspp/libpspp.la gl/libgl.la
 
 tests_libpspp_stringi_map_test_SOURCES = \
-       src/libpspp/hash-functions.c \
-       src/libpspp/hmap.c \
-       src/libpspp/pool.c \
-       src/libpspp/str.c \
-       src/libpspp/stringi-map.c \
-       src/libpspp/string-set.c \
-       src/libpspp/stringi-set.c \
-       src/libpspp/temp-file.c \
        tests/libpspp/stringi-map-test.c
 tests_libpspp_stringi_map_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10
+tests_libpspp_stringi_map_test_LDADD = src/libpspp/libpspp.la gl/libgl.la
 
 tests_libpspp_string_set_test_SOURCES = \
        src/libpspp/hash-functions.c \
@@ -133,47 +119,27 @@ tests_libpspp_string_set_test_SOURCES = \
 tests_libpspp_string_set_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10
 
 tests_libpspp_stringi_set_test_SOURCES = \
-       src/libpspp/hash-functions.c \
-       src/libpspp/hmap.c \
-       src/libpspp/pool.c \
-       src/libpspp/str.c \
-       src/libpspp/stringi-set.c \
-       src/libpspp/temp-file.c \
        tests/libpspp/stringi-set-test.c
 tests_libpspp_stringi_set_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10
+tests_libpspp_stringi_set_test_LDADD = src/libpspp/libpspp.la gl/libgl.la
 
 tests_libpspp_tower_test_SOURCES = \
-       src/libpspp/abt.c \
-       src/libpspp/pool.c \
-       src/libpspp/temp-file.c \
-       src/libpspp/tower.c \
        tests/libpspp/tower-test.c
 tests_libpspp_tower_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10
+tests_libpspp_tower_test_LDADD = src/libpspp/libpspp.la gl/libgl.la
 
 tests_libpspp_u8_istream_test_SOURCES = tests/libpspp/u8-istream-test.c
 tests_libpspp_u8_istream_test_LDADD = src/libpspp/libpspp.la gl/libgl.la
 
 tests_libpspp_sparse_array_test_SOURCES = \
-       src/libpspp/sparse-array.c \
-       src/libpspp/pool.c \
-       tests/libpspp/sparse-array-test.c \
-       src/libpspp/temp-file.c
+       tests/libpspp/sparse-array-test.c 
 tests_libpspp_sparse_array_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10
+tests_libpspp_sparse_array_test_LDADD = src/libpspp/libpspp.la gl/libgl.la
 
 tests_libpspp_sparse_xarray_test_SOURCES = \
-       src/libpspp/argv-parser.c \
-       src/libpspp/bt.c \
-       src/libpspp/deque.c \
-       src/libpspp/ext-array.c \
-       src/libpspp/model-checker.c \
-       src/libpspp/range-set.c \
-       src/libpspp/sparse-array.c \
-       src/libpspp/sparse-xarray.c \
-       src/libpspp/str.c \
-       src/libpspp/pool.c \
-       src/libpspp/temp-file.c \
        tests/libpspp/sparse-xarray-test.c
 tests_libpspp_sparse_xarray_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10
+tests_libpspp_sparse_xarray_test_LDADD = src/libpspp/libpspp.la gl/libgl.la
 
 tests_data_inexactify_SOURCES = tests/data/inexactify.c
 
@@ -194,24 +160,31 @@ tests_language_lexer_scan_test_SOURCES = \
        src/language/lexer/scan.c \
        src/language/lexer/segment.c \
        src/language/lexer/token.c \
-       src/libpspp/pool.c \
-       src/libpspp/prompt.c \
-       src/libpspp/str.c \
-       src/libpspp/temp-file.c \
        tests/language/lexer/scan-test.c
 tests_language_lexer_scan_test_CFLAGS = $(AM_CFLAGS)
+tests_language_lexer_scan_test_LDADD = \
+       src/libpspp/libpspp.la \
+       gl/libgl.la 
 
 check_PROGRAMS += tests/language/lexer/segment-test
 tests_language_lexer_segment_test_SOURCES = \
        src/data/identifier.c \
        src/language/lexer/command-name.c \
        src/language/lexer/segment.c \
-       src/libpspp/pool.c \
-       src/libpspp/prompt.c \
-       src/libpspp/str.c \
-       src/libpspp/temp-file.c \
        tests/language/lexer/segment-test.c
 tests_language_lexer_segment_test_CFLAGS = $(AM_CFLAGS)
+tests_language_lexer_segment_test_LDADD = \
+       src/libpspp/libpspp.la \
+       gl/libgl.la 
+
+check_PROGRAMS += tests/libpspp/zip-test
+tests_libpspp_zip_test_SOURCES = \
+       tests/libpspp/zip-test.c
+tests_libpspp_zip_test_CFLAGS = $(AM_CFLAGS)
+tests_libpspp_zip_test_LDADD = \
+       src/libpspp/libpspp.la \
+       gl/libgl.la 
+
 
 check_PROGRAMS += tests/output/render-test
 tests_output_render_test_SOURCES = tests/output/render-test.c
@@ -231,7 +204,8 @@ EXTRA_DIST += \
        tests/data/num-out.expected.cmp.gz \
        tests/data/v13.sav \
        tests/data/v14.sav \
-        tests/language/data-io/Book1.gnm.unzipped
+        tests/language/data-io/Book1.gnm.unzipped \
+        tests/language/data-io/test.ods
 
 CLEANFILES += *.save pspp.* foo*
 
@@ -266,7 +240,7 @@ TESTSUITE_AT = \
        tests/language/data-io/data-reader.at \
        tests/language/data-io/dataset.at \
        tests/language/data-io/file-handle.at \
-       tests/language/data-io/get-data-gnm.at \
+       tests/language/data-io/get-data-spreadsheet.at \
        tests/language/data-io/get-data-psql.at \
        tests/language/data-io/get-data-txt.at \
        tests/language/data-io/get.at \
@@ -306,6 +280,7 @@ TESTSUITE_AT = \
        tests/language/stats/factor.at \
        tests/language/stats/flip.at \
        tests/language/stats/frequencies.at \
+       tests/language/stats/glm.at \
        tests/language/stats/npar.at \
        tests/language/stats/oneway.at \
        tests/language/stats/quick-cluster.at \
@@ -348,6 +323,7 @@ TESTSUITE_AT = \
        tests/libpspp/stringi-set.at \
        tests/libpspp/tower.at \
        tests/libpspp/u8-istream.at \
+       tests/libpspp/zip.at \
        tests/math/moments.at \
        tests/math/randist.at \
        tests/output/ascii.at \
diff --git a/tests/language/data-io/get-data-gnm.at b/tests/language/data-io/get-data-gnm.at
deleted file mode 100644 (file)
index 92815dc..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-AT_BANNER([GET DATA /TYPE=GNM])
-
-AT_SETUP([GET DATA /TYPE=GNM with CELLRANGE])
-AT_SKIP_IF([test "$GNM_SUPPORT" = no])
-AT_CHECK([gzip -c $top_srcdir/tests/language/data-io/Book1.gnm.unzipped > Book1.gnumeric])
-AT_DATA([get-data.sps], [dnl
-GET DATA /TYPE=gnm /FILE='Book1.gnumeric'  /READNAMES=off /SHEET=name 'This' /CELLRANGE=range 'g9:i13' .
-DISPLAY VARIABLES.
-LIST.
-])
-AT_CHECK([pspp -o pspp.csv get-data.sps])
-AT_CHECK([cat pspp.csv], [0], [dnl
-Variable,Description,,Position
-VAR001,Format: F8.2,,1
-,Measure: Scale,,
-,Display Alignment: Right,,
-,Display Width: 8,,
-VAR002,Format: A8,,2
-,Measure: Nominal,,
-,Display Alignment: Left,,
-,Display Width: 8,,
-VAR003,Format: F8.2,,3
-,Measure: Scale,,
-,Display Alignment: Right,,
-,Display Width: 8,,
-
-Table: Data List
-VAR001,VAR002,VAR003
-.00,fred    ,20.00
-1.00,11      ,21.00
-2.00,twelve  ,22.00
-3.00,13      ,23.00
-4.00,14      ,24.00
-])
-AT_CLEANUP
-
-AT_SETUP([GET DATA /TYPE=GNM with CELLRANGE and READNAMES])
-AT_SKIP_IF([test "$GNM_SUPPORT" = no])
-AT_CHECK([gzip -c $top_srcdir/tests/language/data-io/Book1.gnm.unzipped > Book1.gnumeric])
-AT_DATA([get-data.sps], [dnl
-GET DATA /TYPE=gnm /FILE='Book1.gnumeric'  /READNAMES=on /SHEET=name 'This' /CELLRANGE=range 'g8:i13' .
-DISPLAY VARIABLES.
-LIST.
-])
-AT_CHECK([pspp -o pspp.csv get-data.sps])
-AT_CHECK([cat pspp.csv], [0], [dnl
-Variable,Description,,Position
-V1,Format: F8.2,,1
-,Measure: Scale,,
-,Display Alignment: Right,,
-,Display Width: 8,,
-V2,Format: A8,,2
-,Measure: Nominal,,
-,Display Alignment: Left,,
-,Display Width: 8,,
-VAR001,Format: F8.2,,3
-,Measure: Scale,,
-,Display Alignment: Right,,
-,Display Width: 8,,
-
-Table: Data List
-V1,V2,VAR001
-.00,fred    ,20.00
-1.00,11      ,21.00
-2.00,twelve  ,22.00
-3.00,13      ,23.00
-4.00,14      ,24.00
-])
-AT_CLEANUP
-
-AT_SETUP([GET DATA /TYPE=GNM without CELLRANGE])
-AT_SKIP_IF([test "$GNM_SUPPORT" = no])
-AT_CHECK([gzip -c $top_srcdir/tests/language/data-io/Book1.gnm.unzipped > Book1.gnumeric])
-AT_DATA([get-data.sps], [dnl
-GET DATA /TYPE=gnm /FILE='Book1.gnumeric' /SHEET=index 3.
-DISPLAY VARIABLES.
-LIST.
-])
-AT_CHECK([pspp -o pspp.csv get-data.sps])
-AT_CHECK([cat pspp.csv], [0], [dnl
-Variable,Description,,Position
-name,Format: A8,,1
-,Measure: Nominal,,
-,Display Alignment: Left,,
-,Display Width: 8,,
-id,Format: F8.2,,2
-,Measure: Scale,,
-,Display Alignment: Right,,
-,Display Width: 8,,
-height,Format: F8.2,,3
-,Measure: Scale,,
-,Display Alignment: Right,,
-,Display Width: 8,,
-
-Table: Data List
-name,id,height
-fred    ,.00,23.40
-bert    ,1.00,.56
-charlie ,2.00,.  @&t@
-dick    ,3.00,-34.09
-])
-AT_CLEANUP
-
-AT_SETUP([GET DATA /TYPE=GNM with missing data])
-AT_SKIP_IF([test "$GNM_SUPPORT" = no])
-AT_CHECK([gzip -c $top_srcdir/tests/language/data-io/Book1.gnm.unzipped > Book1.gnumeric])
-AT_DATA([get-data.sps], [dnl
-* This sheet has no data in one of its variables
-GET DATA /TYPE=gnm /FILE='Book1.gnumeric' /READNAMES=on /SHEET=index 5.
-DISPLAY VARIABLES.
-LIST.
-])
-AT_CHECK([pspp -o pspp.csv get-data.sps])
-AT_CHECK([cat pspp.csv], [0], [dnl
-Variable,Description,,Position
-vone,Format: F8.2,,1
-,Measure: Scale,,
-,Display Alignment: Right,,
-,Display Width: 8,,
-vtwo,Format: F8.2,,2
-,Measure: Scale,,
-,Display Alignment: Right,,
-,Display Width: 8,,
-vthree,Format: A8,,3
-,Measure: Nominal,,
-,Display Alignment: Left,,
-,Display Width: 8,,
-v4,Format: F8.2,,4
-,Measure: Scale,,
-,Display Alignment: Right,,
-,Display Width: 8,,
-
-Table: Data List
-vone,vtwo,vthree,v4
-1.00,3.00,,5.00
-2.00,4.00,,6.00
-])
-AT_CLEANUP
-
-AT_SETUP([GET DATA /TYPE=GNM with empty sheet])
-AT_SKIP_IF([test "$GNM_SUPPORT" = no])
-AT_CHECK([gzip -c $top_srcdir/tests/language/data-io/Book1.gnm.unzipped > Book1.gnumeric])
-AT_DATA([get-data.sps], [dnl
-* This sheet is empty
-GET DATA /TYPE=gnm /FILE='Book1.gnumeric' /SHEET=name 'Empty'.
-])
-AT_CHECK([pspp -o pspp.csv get-data.sps], [0], [dnl
-warning: Selected sheet or range of spreadsheet `Book1.gnumeric' is empty.
-])
-AT_CLEANUP
-
-AT_SETUP([GET DATA /TYPE=GNM with nonexistent sheet])
-AT_SKIP_IF([test "$GNM_SUPPORT" = no])
-AT_CHECK([gzip -c $top_srcdir/tests/language/data-io/Book1.gnm.unzipped > Book1.gnumeric])
-AT_DATA([get-data.sps], [dnl
-* This sheet doesnt exist.
-GET DATA /TYPE=gnm /FILE='Book1.gnumeric' /SHEET=name 'foobarxx'.
-])
-AT_CHECK([pspp -o pspp.csv get-data.sps], [0], [dnl
-warning: Selected sheet or range of spreadsheet `Book1.gnumeric' is empty.
-])
-AT_CLEANUP
diff --git a/tests/language/data-io/get-data-spreadsheet.at b/tests/language/data-io/get-data-spreadsheet.at
new file mode 100644 (file)
index 0000000..19b8964
--- /dev/null
@@ -0,0 +1,181 @@
+
+m4_define([SPREADSHEET_TEST_PREP],[dnl
+ m4_if($1,[GNM],[dnl
+    AT_CHECK([gzip -c $top_srcdir/tests/language/data-io/Book1.gnm.unzipped > Book1.gnumeric])dnl
+    m4_define([testsheet],[Book1.gnumeric])dnl
+    AT_SKIP_IF([test n$GNM_SUPPORT != nyes])dnl
+    ]) dnl
+ m4_if($1,[ODS],[dnl
+    AT_CHECK([cp $top_srcdir/tests/language/data-io/test.ods test.ods])dnl
+    m4_define([testsheet],[test.ods])dnl
+    AT_SKIP_IF([test n$ODF_READ_SUPPORT != nyes])dnl
+    ])dnl
+])
+
+m4_define([CHECK_SPREADSHEET_READER],
+ [dnl
+AT_SETUP([GET DATA /TYPE=$1 with CELLRANGE])
+SPREADSHEET_TEST_PREP($1)
+AT_DATA([get-data.sps], [dnl
+GET DATA /TYPE=$1 /FILE='testsheet'  /READNAMES=off /SHEET=name 'This' /CELLRANGE=range 'g9:i13' .
+DISPLAY VARIABLES.
+LIST.
+])
+AT_CHECK([pspp -o pspp.csv get-data.sps])
+AT_CHECK([cat pspp.csv], [0], [dnl
+Variable,Description,,Position
+VAR001,Format: F8.2,,1
+,Measure: Scale,,
+,Display Alignment: Right,,
+,Display Width: 8,,
+VAR002,Format: A8,,2
+,Measure: Nominal,,
+,Display Alignment: Left,,
+,Display Width: 8,,
+VAR003,Format: F8.2,,3
+,Measure: Scale,,
+,Display Alignment: Right,,
+,Display Width: 8,,
+
+Table: Data List
+VAR001,VAR002,VAR003
+.00,fred    ,20.00
+1.00,11      ,21.00
+2.00,twelve  ,22.00
+3.00,13      ,23.00
+4.00,14      ,24.00
+])
+AT_CLEANUP
+
+AT_SETUP([GET DATA /TYPE=$1 with CELLRANGE and READNAMES])
+SPREADSHEET_TEST_PREP($1)
+AT_DATA([get-data.sps], [dnl
+GET DATA /TYPE=$1 /FILE='testsheet'  /READNAMES=on /SHEET=name 'This' /CELLRANGE=range 'g8:i13' .
+DISPLAY VARIABLES.
+LIST.
+])
+AT_CHECK([pspp -o pspp.csv get-data.sps])
+AT_CHECK([cat pspp.csv], [0], [dnl
+Variable,Description,,Position
+V1,Format: F8.2,,1
+,Measure: Scale,,
+,Display Alignment: Right,,
+,Display Width: 8,,
+V2,Format: A8,,2
+,Measure: Nominal,,
+,Display Alignment: Left,,
+,Display Width: 8,,
+VAR001,Format: F8.2,,3
+,Measure: Scale,,
+,Display Alignment: Right,,
+,Display Width: 8,,
+
+Table: Data List
+V1,V2,VAR001
+.00,fred    ,20.00
+1.00,11      ,21.00
+2.00,twelve  ,22.00
+3.00,13      ,23.00
+4.00,14      ,24.00
+])
+AT_CLEANUP
+
+AT_SETUP([GET DATA /TYPE=$1 without CELLRANGE])
+SPREADSHEET_TEST_PREP($1)
+AT_DATA([get-data.sps], [dnl
+GET DATA /TYPE=$1 /FILE='testsheet' /SHEET=index 3.
+DISPLAY VARIABLES.
+LIST.
+])
+AT_CHECK([pspp -o pspp.csv get-data.sps])
+AT_CHECK([cat pspp.csv], [0], [dnl
+Variable,Description,,Position
+name,Format: A8,,1
+,Measure: Nominal,,
+,Display Alignment: Left,,
+,Display Width: 8,,
+id,Format: F8.2,,2
+,Measure: Scale,,
+,Display Alignment: Right,,
+,Display Width: 8,,
+height,Format: F8.2,,3
+,Measure: Scale,,
+,Display Alignment: Right,,
+,Display Width: 8,,
+
+Table: Data List
+name,id,height
+fred    ,.00,23.40
+bert    ,1.00,.56
+charlie ,2.00,.  @&t@
+dick    ,3.00,-34.09
+])
+AT_CLEANUP
+
+AT_SETUP([GET DATA /TYPE=$1 with missing data])
+SPREADSHEET_TEST_PREP($1)
+AT_DATA([get-data.sps], [dnl
+* This sheet has no data in one of its variables
+GET DATA /TYPE=$1 /FILE='testsheet' /READNAMES=on /SHEET=index 5.
+DISPLAY VARIABLES.
+LIST.
+])
+AT_CHECK([pspp -o pspp.csv get-data.sps])
+AT_CHECK([cat pspp.csv], [0], [dnl
+Variable,Description,,Position
+vone,Format: F8.2,,1
+,Measure: Scale,,
+,Display Alignment: Right,,
+,Display Width: 8,,
+vtwo,Format: F8.2,,2
+,Measure: Scale,,
+,Display Alignment: Right,,
+,Display Width: 8,,
+vthree,Format: A8,,3
+,Measure: Nominal,,
+,Display Alignment: Left,,
+,Display Width: 8,,
+v4,Format: F8.2,,4
+,Measure: Scale,,
+,Display Alignment: Right,,
+,Display Width: 8,,
+
+Table: Data List
+vone,vtwo,vthree,v4
+1.00,3.00,,5.00
+2.00,4.00,,6.00
+])
+AT_CLEANUP
+
+AT_SETUP([GET DATA /TYPE=$1 with empty sheet])
+SPREADSHEET_TEST_PREP($1)
+AT_DATA([get-data.sps], [dnl
+* This sheet is empty
+GET DATA /TYPE=$1 /FILE='testsheet' /SHEET=name 'Empty'.
+])
+AT_CHECK([pspp -o pspp.csv get-data.sps], [0], [dnl
+warning: Selected sheet or range of spreadsheet `testsheet' is empty.
+])
+AT_CLEANUP
+
+AT_SETUP([GET DATA /TYPE=$1 with nonexistent sheet])
+SPREADSHEET_TEST_PREP($1)
+AT_DATA([get-data.sps], [dnl
+* This sheet doesnt exist.
+GET DATA /TYPE=$1 /FILE='testsheet' /SHEET=name 'foobarxx'.
+])
+AT_CHECK([pspp -o pspp.csv get-data.sps], [0], [dnl
+warning: Selected sheet or range of spreadsheet `testsheet' is empty.
+])
+AT_CLEANUP
+])
+
+
+AT_BANNER([GET DATA Spreadsheet /TYPE=GNM])
+
+CHECK_SPREADSHEET_READER([GNM])
+
+AT_BANNER([GET DATA Spreadsheet /TYPE=ODS])
+
+CHECK_SPREADSHEET_READER([ODS])
+
diff --git a/tests/language/data-io/test.ods b/tests/language/data-io/test.ods
new file mode 100644 (file)
index 0000000..c079454
Binary files /dev/null and b/tests/language/data-io/test.ods differ
index 7f5e6eb376aec3e421bc4f4490a791bb56083d14..c3d8d3cc7745e4ca2396059a46640eec58bb0a3b 100644 (file)
@@ -206,3 +206,34 @@ four        ,nought,2.00,4.00
 ])
 
 AT_CLEANUP
+
+
+
+AT_SETUP([AUTORECODE /blank])
+
+AT_DATA([auto-blank.sps],  [dnl
+data list notable list /x (a8) y * z (a16).
+begin data.
+one   2  fred
+two   4  ""
+""    4  fred
+""    2  charliebrown
+three 2  charliebrown
+end data.
+
+autorecode variables x y z into a b c  /blank=missing.
+
+list a b c y.
+])
+
+AT_CHECK([pspp -O format=csv auto-blank.sps], [0], [dnl
+Table: Data List
+a,b,c,y
+1.00,1.00,2.00,2.00
+3.00,2.00,.  ,4.00
+.  ,2.00,2.00,4.00
+.  ,1.00,1.00,2.00
+2.00,1.00,1.00,2.00
+])
+
+AT_CLEANUP
diff --git a/tests/language/stats/glm.at b/tests/language/stats/glm.at
new file mode 100644 (file)
index 0000000..68caf60
--- /dev/null
@@ -0,0 +1,72 @@
+AT_BANNER([GLM procedure])
+
+AT_SETUP([GLM latin square design])
+
+dnl This example comes from :
+dnl  http://ssnds.uwo.ca/statsexamples/spssanova/latinsquareresults.html
+AT_DATA([latin.sps], [dnl
+set format = F20.3.
+data list notable  fixed /a 1 b 3 c 5 y 7-10(2).
+begin data.
+1 1 6  3.5
+1 2 2  8.9
+1 3 3  9.6
+1 4 4 10.5
+1 5 5  3.1
+1 6 1  5.9
+2 1 2  4.2
+2 2 6  1.9
+2 3 5  3.7
+2 4 3 10.2
+2 5 1  7.2
+2 6 4  7.6
+3 1 1  6.7
+3 2 4  5.8
+3 3 6 -2.7
+3 4 2  4.6
+3 5 3  4.0
+3 6 5 -0.7
+4 1 4  6.6
+4 2 1  4.5
+4 3 2  3.7
+4 4 5  3.7
+4 5 6 -3.3
+4 6 3  3.0
+5 1 3  4.1
+5 2 5  2.4
+5 3 4  6.0
+5 4 1  5.1
+5 5 2  3.5
+5 6 6  4.0
+6 1 5  3.8
+6 2 3  5.8
+6 3 1  7.0
+6 4 6  3.8
+6 5 4  5.0
+6 6 2  8.6
+end data.
+
+variable labels a 'Factor A' b 'Factor B' c 'Factor C' y 'Criterion'.
+
+glm y by   b a c
+  /method=sstype(3)
+  /intercept=include
+  /criteria=alpha(.05)
+  /design = a b c
+  .
+])
+
+AT_CHECK([pspp -O format=csv latin.sps | sed 's/329.62[[678]]/329.62/'], [0],
+  [Table: Tests of Between-Subjects Effects
+Source,Type III Sum of Squares,df,Mean Square,F,Sig.
+Corrected Model,263.064,15,17.538,5.269,.000
+Intercept,815.103,1,815.103,244.910,.000
+Factor A,78.869,5,15.774,4.739,.005
+Factor B,28.599,5,5.720,1.719,.176
+Factor C,155.596,5,31.119,9.350,.000
+Error,66.563,20,3.328,,
+Total,1144.730,36,,,
+Corrected Total,329.62,35,,,
+])
+
+AT_CLEANUP
index 57193c00685249db3f24bbbbf8e064bc6144a422..cc1bd167c5cc81f8a09ef318c5d4f7a483ecc763 100644 (file)
@@ -526,13 +526,13 @@ AT_CHECK([pspp -o pspp.csv npar.sps])
 AT_CHECK([cat pspp.csv], [0], [dnl
 Table: Ranks
 ,,N,Mean Rank,Sum of Ranks
-second - first,Negative Ranks,5,8.60,43.00
-,Positive Ranks,8,6.00,48.00
+first - second,Negative Ranks,8,6.00,48.00
+,Positive Ranks,5,8.60,43.00
 ,Ties,2,,
 ,Total,15,,
 
 Table: Test Statistics
-,second - first
+,first - second
 Z,-.18
 Asymp. Sig. (2-tailed),.86
 Exact Sig. (2-tailed),.89
@@ -575,13 +575,13 @@ dnl This is the same output as the previous test.
 AT_CHECK([cat pspp.csv], [0], [dnl
 Table: Ranks
 ,,N,Mean Rank,Sum of Ranks
-second - first,Negative Ranks,5,8.60,43.00
-,Positive Ranks,8,6.00,48.00
+first - second,Negative Ranks,8,6.00,48.00
+,Positive Ranks,5,8.60,43.00
 ,Ties,2,,
 ,Total,15,,
 
 Table: Test Statistics
-,second - first
+,first - second
 Z,-.18
 Asymp. Sig. (2-tailed),.86
 Exact Sig. (2-tailed),.89
@@ -615,17 +615,17 @@ dnl (see bug #31611).
 AT_CHECK([sed 's/\.313$/.312/' pspp.csv], [0], [dnl
 Table: Frequencies
 ,,N
-height - age,Negative Differences,1
-,Positive Differences,3
+age - height,Negative Differences,3
+,Positive Differences,1
 ,Ties,2
 ,Total,6
-rank - height,Negative Differences,3
-,Positive Differences,2
+height - rank,Negative Differences,2
+,Positive Differences,3
 ,Ties,1
 ,Total,6
 
 Table: Test Statistics
-,height - age,rank - height
+,age - height,height - rank
 Exact Sig. (2-tailed),.625,1.000
 Exact Sig. (1-tailed),.312,.500
 Point Probability,.250,.312
@@ -854,7 +854,7 @@ Table: Runs Test
 ,score
 Test Value (median),3.0000
 Cases < Test Value,177.0000
-Cases >= Test Value,309.0000
+Cases  Test Value,309.0000
 Total Cases,486.0000
 Number of Runs,12
 Z,-20.9931
@@ -864,7 +864,7 @@ Table: Runs Test
 ,score
 Test Value (mean),3.6379
 Cases < Test Value,259.0000
-Cases >= Test Value,227.0000
+Cases  Test Value,227.0000
 Total Cases,486.0000
 Number of Runs,12
 Z,-21.0650
@@ -874,7 +874,7 @@ Table: Runs Test
 ,score
 Test Value (mode),6.0000
 Cases < Test Value,316.0000
-Cases >= Test Value,170.0000
+Cases  Test Value,170.0000
 Total Cases,486.0000
 Number of Runs,11
 Z,-21.0742
@@ -1093,3 +1093,299 @@ Asymp. Sig.,.001
 ])
 
 AT_CLEANUP
+
+
+
+AT_SETUP([NPAR TESTS McNemar])
+
+AT_DATA([mcnemar.sps], [dnl
+set format = F12.3.
+data list notable list /v1 * v2 * junk *.
+begin data.
+0 0 0
+0 0 0
+0 0 0
+0 0 0
+0 1 0
+0 1 0
+0 1 0
+0 1 0
+0 1 1
+0 1 1
+0 1 1
+0 1 1
+0 1 1
+1 0 1
+1 0 1
+1 1 1
+1 1 1
+1 1 0
+1 1 0
+1 1 1
+end data.
+
+npar tests 
+     /mcnemar = v1 WITH v2 junk.
+])
+
+AT_CHECK([pspp -O format=csv mcnemar.sps], [0], [dnl
+Table: v1 & v2
+v1,v2,
+,.000,1.000
+.000,4,9
+1.000,2,5
+
+Table: v1 & junk
+v1,junk,
+,.000,1.000
+.000,8,5
+1.000,2,5
+
+Table: Test Statistics
+,N,Exact Sig. (2-tailed),Exact Sig. (1-tailed),Point Probability
+v1 & v2,20,.065,.033,.027
+v1 & junk,20,.453,.227,.164
+])
+
+AT_CLEANUP
+
+
+AT_SETUP([NPAR TESTS Kolmogorov-Smirnov Uniform parameters given])
+
+AT_DATA([ks-uniform.sps], [dnl
+set format F12.3.
+data list notable list /x *.
+begin data
+.554
+.382
+.329
+.480
+.711
+.503
+.203
+.477
+.621
+.581
+end data.
+
+npar tests k-s (uniform 0 1) = x.
+])
+
+AT_CHECK([pspp -O format=csv ks-uniform.sps], [0], [dnl
+Table: One-Sample Kolmogorov-Smirnov Test
+,,x
+N,,10
+Uniform Parameters,Minimum,.000
+,Maximum,1.000
+Most Extreme Differences,Absolute,.289
+,Positive,.289
+,Negative,-.229
+Kolmogorov-Smirnov Z,,.914
+Asymp. Sig. (2-tailed),,.374
+])
+
+AT_CLEANUP
+
+
+AT_SETUP([NPAR TESTS Kolmogorov-Smirnov Normal parameters imputed])
+
+AT_DATA([ks-normal.sps], [dnl
+set format = F12.3.
+
+data list notable list /foo * bar *.
+begin data.
+65 12.5
+59 14.2
+43 12.6
+57 
+68 
+79 
+51 
+62 
+57  
+73 
+58 
+58 
+68 
+75 
+47 
+70 
+59 
+71 
+52 
+48 13.0
+58 14.1
+37 15.0
+39 13.1
+58 13.2
+43 14.5
+58 13.5
+86 14.0
+63 12.5
+80 12.8
+70 
+63 
+53 
+53 
+48 
+49 
+51 
+47 
+81 
+66 
+78 
+65
+69 
+70 12.1
+63 12.5
+64 12.4
+39 13.8
+51 13.2
+68 14.0
+76 12.6
+53 12.1
+71 13.5
+47 13.8
+87 14.1
+72 12.9
+48 12.1
+75 12.8
+51 13.4
+63 13.9
+61 12.5
+61 12.4
+66 12.8
+82 12.9
+81 13.6
+46 
+52 
+71 
+73 
+58 
+57 
+46 
+58 
+52 13.5
+71 13.2
+57 12.8
+78 14.1
+73 12.1
+50 12.6
+71
+51
+51
+68
+84
+64
+66
+65
+52
+56
+70
+68
+66
+78
+65
+71
+53
+81
+53
+57
+64
+61
+43
+56
+37
+74
+66
+81
+67
+80
+68
+76
+70
+80
+42
+74
+80
+70
+60
+39
+72
+69
+63
+72
+63
+49
+53 13.2
+43 13.8
+51 12.5
+63 12.6
+64 12.9
+65 13.0
+64 12.5
+66 12.0
+55 
+62 
+58 
+48 
+67 
+46 
+36 
+61 
+55 
+77 
+74 
+60 
+70  
+69 
+57 
+49 
+63 
+69 
+63 
+76 
+53 
+54 
+42 
+64 
+66 
+61 
+62 
+73 
+73 
+60 
+79 
+40 
+48 
+76 
+60 
+76 
+54
+69
+65
+69
+51
+54
+82
+end data.
+
+npar tests 
+       /k-s (normal) = foo bar.
+])
+
+AT_CHECK([pspp -O format=csv ks-normal.sps], [0], [dnl
+Table: One-Sample Kolmogorov-Smirnov Test
+,,foo,bar
+N,,174,48
+Normal Parameters,Mean,62.109,13.108
+,Std. Deviation,11.548,.718
+Most Extreme Differences,Absolute,.059,.115
+,Positive,.055,.115
+,Negative,-.059,-.082
+Kolmogorov-Smirnov Z,,.785,.795
+Asymp. Sig. (2-tailed),,.569,.552
+])
+
+
+AT_CLEANUP
index a0a3bafb745abeff97c97e06f8213a0bb328543c..ce121beb977dac2bda33886450fd4689d24e09e9 100644 (file)
@@ -546,8 +546,358 @@ ONEWAY
 
 AT_CHECK([pspp -o pspp-weighted.csv oneway-weighted.sps], [0], [ignore], [ignore])
 
-
 AT_CHECK([diff pspp-weighted.csv pspp-unweighted.csv], [0])
 
+AT_CLEANUP
+
+
+
+AT_SETUP([ONEWAY posthoc LSD and BONFERRONI])
+AT_DATA([oneway-pig.sps],[dnl
+SET FORMAT F12.3.
+data list notable list /pigmentation * family *.
+begin data.
+36 1
+39 1
+43 1
+38 1
+37 1
+46 2
+47 2
+47 2
+47 2
+43 2
+40 3
+50 3
+44 3
+48 3
+50 3
+45 4
+53 4
+56 4
+52 4
+56 4
+end data.
+
+
+oneway pigmentation by family
+       /statistics = descriptives
+       /posthoc = lsd bonferroni alpha (0.05)
+        .
+])
+
+AT_CHECK([pspp -O format=csv oneway-pig.sps], [0], 
+[Table: Descriptives
+,,,,,,95% Confidence Interval for Mean,,,
+,,N,Mean,Std. Deviation,Std. Error,Lower Bound,Upper Bound,Minimum,Maximum
+pigmentation,1.000,5,38.600,2.702,1.208,35.245,41.955,36.000,43.000
+,2.000,5,46.000,1.732,.775,43.849,48.151,43.000,47.000
+,3.000,5,46.400,4.336,1.939,41.016,51.784,40.000,50.000
+,4.000,5,52.400,4.506,2.015,46.806,57.994,45.000,56.000
+,Total,20,45.850,5.967,1.334,43.057,48.643,36.000,56.000
+
+Table: ANOVA
+,,Sum of Squares,df,Mean Square,F,Significance
+pigmentation,Between Groups,478.950,3,159.650,12.927,.000
+,Within Groups,197.600,16,12.350,,
+,Total,676.550,19,,,
+
+Table: Multiple Comparisons
+,,,Mean Difference,,,95% Confidence Interval,
+,(I) family,(J) family,(I - J),Std. Error,Sig.,Lower Bound,Upper Bound
+LSD,1.000,2.000,-7.400,2.223,.004,-12.112,-2.688
+,,3.000,-7.800,2.223,.003,-12.512,-3.088
+,,4.000,-13.800,2.223,.000,-18.512,-9.088
+,2.000,1.000,7.400,2.223,.004,2.688,12.112
+,,3.000,-.400,2.223,.859,-5.112,4.312
+,,4.000,-6.400,2.223,.011,-11.112,-1.688
+,3.000,1.000,7.800,2.223,.003,3.088,12.512
+,,2.000,.400,2.223,.859,-4.312,5.112
+,,4.000,-6.000,2.223,.016,-10.712,-1.288
+,4.000,1.000,13.800,2.223,.000,9.088,18.512
+,,2.000,6.400,2.223,.011,1.688,11.112
+,,3.000,6.000,2.223,.016,1.288,10.712
+Bonferroni,1.000,2.000,-7.400,2.223,.025,-14.086,-.714
+,,3.000,-7.800,2.223,.017,-14.486,-1.114
+,,4.000,-13.800,2.223,.000,-20.486,-7.114
+,2.000,1.000,7.400,2.223,.025,.714,14.086
+,,3.000,-.400,2.223,1.000,-7.086,6.286
+,,4.000,-6.400,2.223,.065,-13.086,.286
+,3.000,1.000,7.800,2.223,.017,1.114,14.486
+,,2.000,.400,2.223,1.000,-6.286,7.086
+,,4.000,-6.000,2.223,.095,-12.686,.686
+,4.000,1.000,13.800,2.223,.000,7.114,20.486
+,,2.000,6.400,2.223,.065,-.286,13.086
+,,3.000,6.000,2.223,.095,-.686,12.686
+])
+
+AT_CLEANUP
+
+
+AT_SETUP([ONEWAY posthoc Tukey HSD and Games-Howell])
+AT_DATA([oneway-tukey.sps],[dnl
+set format = f11.3.
+data list notable list /libido * dose *.
+begin data.
+3 0
+2 0
+1 0
+1 0
+4 0
+5 1
+2 1
+4 1
+2 1
+3 1
+7 2
+4 2
+5 2
+3 2
+6 2
+end data.
+
+variable label dose 'Dose of Viagra'.
+
+add value labels dose 0 'Placebo' 1 '1 Dose' 2 '2 Doses'.
+
+oneway libido by dose
+       /posthoc tukey gh.
+])
+
+AT_CHECK([pspp -O format=csv oneway-tukey.sps], [0], 
+[Table: ANOVA
+,,Sum of Squares,df,Mean Square,F,Significance
+libido,Between Groups,20.133,2,10.067,5.119,.025
+,Within Groups,23.600,12,1.967,,
+,Total,43.733,14,,,
+
+Table: Multiple Comparisons
+,,,Mean Difference,,,95% Confidence Interval,
+,(I) Dose of Viagra,(J) Dose of Viagra,(I - J),Std. Error,Sig.,Lower Bound,Upper Bound
+Tukey HSD,Placebo,1 Dose,-1.000,.887,.516,-3.366,1.366
+,,2 Doses,-2.800,.887,.021,-5.166,-.434
+,1 Dose,Placebo,1.000,.887,.516,-1.366,3.366
+,,2 Doses,-1.800,.887,.147,-4.166,.566
+,2 Doses,Placebo,2.800,.887,.021,.434,5.166
+,,1 Dose,1.800,.887,.147,-.566,4.166
+Games-Howell,Placebo,1 Dose,-1.000,.887,.479,-3.356,1.356
+,,2 Doses,-2.800,.887,.039,-5.439,-.161
+,1 Dose,Placebo,1.000,.887,.479,-1.356,3.356
+,,2 Doses,-1.800,.887,.185,-4.439,.839
+,2 Doses,Placebo,2.800,.887,.039,.161,5.439
+,,1 Dose,1.800,.887,.185,-.839,4.439
+])
 
 AT_CLEANUP
+
+AT_SETUP([ONEWAY posthoc Sidak])
+AT_DATA([oneway-sidak.sps],[dnl
+SET FORMAT F20.4.
+
+DATA LIST notable LIST /program score.
+BEGIN DATA.
+1   9
+1  12
+1  14
+1  11
+1  13
+2  10
+2   6
+2   9
+2   9
+2  10
+3  12
+3  14
+3  11
+3  13
+3  11
+4   9
+4   8
+4  11
+4   7
+4   8
+END DATA.
+
+ONEWAY
+  score BY program
+  /MISSING ANALYSIS
+  /POSTHOC = SIDAK.
+])
+
+AT_CHECK([pspp -O format=csv oneway-sidak.sps], [0], 
+[Table: ANOVA
+,,Sum of Squares,df,Mean Square,F,Significance
+score,Between Groups,54.9500,3,18.3167,7.0449,.0031
+,Within Groups,41.6000,16,2.6000,,
+,Total,96.5500,19,,,
+
+Table: Multiple Comparisons
+,,,Mean Difference,,,95% Confidence Interval,
+,(I) program,(J) program,(I - J),Std. Error,Sig.,Lower Bound,Upper Bound
+Šidák,1.0000,2.0000,3.0000,1.0198,.0561,-.0575,6.0575
+,,3.0000,-.4000,1.0198,.9993,-3.4575,2.6575
+,,4.0000,3.2000,1.0198,.0375,.1425,6.2575
+,2.0000,1.0000,-3.0000,1.0198,.0561,-6.0575,.0575
+,,3.0000,-3.4000,1.0198,.0250,-6.4575,-.3425
+,,4.0000,.2000,1.0198,1.0000,-2.8575,3.2575
+,3.0000,1.0000,.4000,1.0198,.9993,-2.6575,3.4575
+,,2.0000,3.4000,1.0198,.0250,.3425,6.4575
+,,4.0000,3.6000,1.0198,.0166,.5425,6.6575
+,4.0000,1.0000,-3.2000,1.0198,.0375,-6.2575,-.1425
+,,2.0000,-.2000,1.0198,1.0000,-3.2575,2.8575
+,,3.0000,-3.6000,1.0198,.0166,-6.6575,-.5425
+])
+
+AT_CLEANUP
+
+AT_SETUP([ONEWAY posthoc Scheffe])
+AT_DATA([oneway-scheffe.sps],[dnl
+set format = f11.3.
+data list notable list /usage * group *.
+begin data.
+21.00     1
+19.00     1
+18.00     1
+25.00     1
+14.00     1
+13.00     1
+24.00     1
+19.00     1
+20.00     1
+21.00     1
+15.00     2
+10.00     2
+13.00     2
+16.00     2
+14.00     2
+24.00     2
+16.00     2
+14.00     2
+18.00     2
+16.00     2
+10.00     3
+ 7.00     3
+13.00     3
+20.00     3
+  .00     3
+ 8.00     3
+ 6.00     3
+ 1.00     3
+12.00     3
+14.00     3
+18.00     4
+15.00     4
+ 3.00     4
+27.00     4
+ 6.00     4
+14.00     4
+13.00     4
+11.00     4
+ 9.00     4
+18.00     4
+end data.
+
+variable label usage 'Days of Use'.
+
+add value labels group 0 'none' 1 'one' 2 'two' 3 'three' 4 'four'.
+
+oneway usage by group
+       /posthoc scheffe.
+])
+
+AT_CHECK([pspp -O format=csv oneway-scheffe.sps], [0], 
+[Table: ANOVA
+,,Sum of Squares,df,Mean Square,F,Significance
+Days of Use,Between Groups,555.275,3,185.092,6.663,.001
+,Within Groups,1000.100,36,27.781,,
+,Total,1555.375,39,,,
+
+Table: Multiple Comparisons
+,,,Mean Difference,,,95% Confidence Interval,
+,(I) group,(J) group,(I - J),Std. Error,Sig.,Lower Bound,Upper Bound
+Scheffé,one,two,3.800,2.357,.467,-3.112,10.712
+,,three,10.300,2.357,.001,3.388,17.212
+,,four,6.000,2.357,.110,-.912,12.912
+,two,one,-3.800,2.357,.467,-10.712,3.112
+,,three,6.500,2.357,.072,-.412,13.412
+,,four,2.200,2.357,.832,-4.712,9.112
+,three,one,-10.300,2.357,.001,-17.212,-3.388
+,,two,-6.500,2.357,.072,-13.412,.412
+,,four,-4.300,2.357,.358,-11.212,2.612
+,four,one,-6.000,2.357,.110,-12.912,.912
+,,two,-2.200,2.357,.832,-9.112,4.712
+,,three,4.300,2.357,.358,-2.612,11.212
+])
+
+AT_CLEANUP
+
+
+AT_SETUP([ONEWAY bad contrast count])
+
+AT_DATA([oneway-bad-contrast.sps],[dnl
+DATA LIST NOTABLE LIST /height * weight * temperature * sex *.
+BEGIN DATA.
+1884     88.6       39.97     0
+1801     90.9       39.03     0
+1801     91.7       38.98     0
+1607     56.3       36.26     1
+1608     46.3       46.26     1
+1607     55.9       37.84     1
+1604     56.6       36.81     1
+1606     56.1       34.56     1
+END DATA.
+
+ONEWAY /VARIABLES= height weight temperature BY sex
+ /CONTRAST = -1  1 
+ /CONTRAST = -3  3 
+ /CONTRAST =  2 -2  1
+ /CONTRAST = -9  9
+ . 
+])
+
+
+AT_CHECK([pspp -O format=csv oneway-bad-contrast.sps], [0], [dnl
+"oneway-bad-contrast.sps:18: warning: ONEWAY: In contrast list 3, the number of coefficients (3) does not equal the number of groups (2). This contrast list will be ignored."
+
+Table: ANOVA
+,,Sum of Squares,df,Mean Square,F,Significance
+height,Between Groups,92629.63,1,92629.63,120.77,.00
+,Within Groups,4601.87,6,766.98,,
+,Total,97231.50,7,,,
+weight,Between Groups,2451.65,1,2451.65,174.59,.00
+,Within Groups,84.25,6,14.04,,
+,Total,2535.90,7,,,
+temperature,Between Groups,1.80,1,1.80,.13,.73
+,Within Groups,84.55,6,14.09,,
+,Total,86.36,7,,,
+
+Table: Contrast Coefficients
+,,sex,
+,,.00,1.00
+Contrast,1,-1,1
+,2,-3,3
+,3,-9,9
+
+Table: Contrast Tests
+,,Contrast,Value of Contrast,Std. Error,t,df,Sig. (2-tailed)
+height,Assume equal variances,1,-222.27,20.23,10.99,6,.00
+,,2,-666.80,60.68,10.99,6,.00
+,,3,-2000.40,182.03,10.99,6,.00
+,Does not assume equal,1,-222.27,27.67,-8.03,2.00,1.98
+,,2,-666.80,83.02,-8.03,2.00,1.98
+,,3,-2000.40,249.07,-8.03,2.00,1.98
+weight,Assume equal variances,1,-36.16,2.74,13.21,6,.00
+,,2,-108.48,8.21,13.21,6,.00
+,,3,-325.44,24.63,13.21,6,.00
+,Does not assume equal,1,-36.16,2.19,-16.48,5.42,2.00
+,,2,-108.48,6.58,-16.48,5.42,2.00
+,,3,-325.44,19.75,-16.48,5.42,2.00
+temperature,Assume equal variances,1,-.98,2.74,.36,6,.73
+,,2,-2.94,8.22,.36,6,.73
+,,3,-8.83,24.67,.36,6,.73
+,Does not assume equal,1,-.98,2.07,-.47,4.19,1.34
+,,2,-2.94,6.22,-.47,4.19,1.34
+,,3,-8.83,18.66,-.47,4.19,1.34
+])
+
+AT_CLEANUP
\ No newline at end of file
index ce28829e512309bd8d5082f0fa346e3e72e854af..9e3e87c899d3635b3e21e46852e48a5e11157691 100644 (file)
@@ -72,3 +72,141 @@ Valid,,500000
 ])
 AT_CLEANUP
 
+
+AT_SETUP([QUICK CLUSTER with weights])
+AT_DATA([qc-weighted.sps], [dnl
+input program.
+loop #i = 1 to 400.
+ compute x = mod (#i, 4).
+ compute w = 5.
+ end case.
+end loop.
+loop #i = 1 to 400.
+ compute x = mod (#i, 4).
+ compute w = 3.
+ end case.
+end loop.
+end file.
+end input program.
+
+weight by w.
+
+QUICK CLUSTER x /CRITERIA = CLUSTER(4) MXITER (100).
+])
+
+AT_CHECK([pspp -o pspp-w.csv qc-weighted.sps])
+
+
+AT_DATA([qc-unweighted.sps], [dnl
+input program.
+loop #i = 1 to 3200.
+ compute x = mod (#i, 4).
+ end case.
+end loop.
+end file.
+end input program.
+
+QUICK CLUSTER x /CRITERIA = CLUSTER(4) MXITER (100).
+])
+
+AT_CHECK([pspp -o pspp-unw.csv qc-unweighted.sps])
+
+AT_CHECK([diff pspp-w.csv pspp-unw.csv], [0])
+
+AT_CLEANUP
+
+AT_SETUP([QUICK CLUSTER with listwise missing])
+AT_DATA([quick-miss.sps], [dnl
+data list notable list /x *.
+begin data.
+1
+1
+2
+3
+4
+.
+2
+end data.
+
+QUICK CLUSTER x /CRITERIA = CLUSTER(4) MXITER (100).
+])
+
+AT_CHECK([pspp -o pspp-m.csv quick-miss.sps])
+
+AT_DATA([quick-nmiss.sps], [dnl
+data list notable list /x *.
+begin data.
+1
+1
+2
+3
+4
+2
+end data.
+
+QUICK CLUSTER x /CRITERIA = CLUSTER(4) MXITER (100).
+])
+
+AT_CHECK([pspp -o pspp-nm.csv quick-nmiss.sps])
+
+AT_CHECK([diff pspp-m.csv pspp-nm.csv], [0])
+
+AT_CLEANUP
+
+
+AT_SETUP([QUICK CLUSTER with pairwise missing])
+AT_DATA([quick-s.sps], [dnl
+data list notable list /x * y *.
+begin data.
+1   2
+1   2.2
+1.1 1.9
+1   9
+1   10
+1.3 9.5
+0.9 8.9
+3.5 2
+3.4 3
+3.5 2.5
+3.1 2.0
+3.9 2.5
+3.8 2.0
+end data.
+
+QUICK CLUSTER x y 
+       /CRITERIA = CLUSTER(3) MXITER (100)
+       .
+])
+
+AT_CHECK([pspp -O format=csv quick-s.sps | tail -5 > pspp-s.csv])
+
+AT_DATA([quick-pw.sps], [dnl
+data list notable list /x * y *.
+begin data.
+1   2
+1   2.2
+1.1 1.9
+1   9
+1   10
+1.3 9.5
+0.9 8.9
+3.5 2
+3.4 3
+3.5 2.5
+3.1 2.0
+3.9 .
+3.8 .
+end data.
+
+QUICK CLUSTER x y 
+       /CRITERIA = CLUSTER(3) MXITER (100)
+       /MISSING = PAIRWISE
+       .
+])
+
+AT_CHECK([pspp -O format=csv quick-pw.sps | tail -5 > pspp-pw.csv])
+
+AT_CHECK([diff pspp-s.csv pspp-pw.csv], [0])
+
+
+AT_CLEANUP
index 90b7ba9e594e7efc9c3d731af72402ed75323870..ceda4c28a1988fc201eac27ffbeab2f15ec6d08f 100644 (file)
@@ -231,10 +231,10 @@ DEP2,F8.0
 
 Table: Group Statistics
 ,INDEP,N,Mean,Std. Deviation,S.E. Mean
-DEP1,1.1,5,2.00,.71,.32
-,2.1,5,4.00,.71,.32
-DEP2,1.1,5,4.00,.71,.32
-,2.1,5,2.00,.71,.32
+DEP1,1.10,5,2.00,.71,.32
+,2.10,5,4.00,.71,.32
+DEP2,1.10,5,4.00,.71,.32
+,2.10,5,2.00,.71,.32
 
 Table: Independent Samples Test
 ,,Levene's Test for Equality of Variances,,t-test for Equality of Means,,,,,,
@@ -285,15 +285,15 @@ DEP,F8.0
 
 Table: Group Statistics
 ,INDEP,N,Mean,Std. Deviation,S.E. Mean
-DEP,>=1.514,11,9.00,3.82,1.15
-,<1.514,11,8.00,2.86,.86
+DEP,≥    1.51,11,9.00,3.82,1.15
+,<    1.51,11,8.00,2.86,.86
 
 Table: Independent Samples Test
 ,,Levene's Test for Equality of Variances,,t-test for Equality of Means,,,,,,
 ,,,,,,,,,95% Confidence Interval of the Difference,
 ,,F,Sig.,t,df,Sig. (2-tailed),Mean Difference,Std. Error Difference,Lower,Upper
-DEP,Equal variances assumed,.17,.68,-.69,20.00,.50,-1.00,1.44,-4.00,2.00
-,Equal variances not assumed,,,-.69,18.54,.50,-1.00,1.44,-4.02,2.02
+DEP,Equal variances assumed,.17,.68,.69,20.00,.50,1.00,1.44,-2.00,4.00
+,Equal variances not assumed,,,.69,18.54,.50,1.00,1.44,-2.02,4.02
 ])
 AT_CLEANUP
 
@@ -320,10 +320,10 @@ dep2,F8.0
 
 Table: Group Statistics
 ,indep,N,Mean,Std. Deviation,S.E. Mean
-dep1,1,3,2.50,.87,.50
-,2,2,3.25,.35,.25
-dep2,1,3,5.00,1.00,.58
-,2,2,2.00,1.41,1.00
+dep1,1.00,3,2.50,.87,.50
+,2.00,2,3.25,.35,.25
+dep2,1.00,3,5.00,1.00,.58
+,2.00,2,2.00,1.41,1.00
 
 Table: Independent Samples Test
 ,,Levene's Test for Equality of Variances,,t-test for Equality of Means,,,,,,
@@ -381,10 +381,10 @@ dep2,F8.0
 
 Table: Group Statistics
 ,indep,N,Mean,Std. Deviation,S.E. Mean
-dep1,1,3,2.50,.87,.50
-,2,3,3.50,.50,.29
-dep2,1,3,5.00,1.00,.58
-,2,3,2.00,1.00,.58
+dep1,1.00,3,2.50,.87,.50
+,2.00,3,3.50,.50,.29
+dep2,1.00,3,5.00,1.00,.58
+,2.00,3,2.00,1.00,.58
 
 Table: Independent Samples Test
 ,,Levene's Test for Equality of Variances,,t-test for Equality of Means,,,,,,
@@ -576,8 +576,8 @@ x,F8.0
 
 Table: Group Statistics
 ,ind,N,Mean,Std. Deviation,S.E. Mean
-x,1,3,2.50,.87,.50
-,2,3,3.50,.50,.29
+x,1.00,3,2.50,.87,.50
+,2.00,3,3.50,.50,.29
 
 Table: Independent Samples Test
 ,,Levene's Test for Equality of Variances,,t-test for Equality of Means,,,,,,
index 03dfb3189e18db2af7798ba1d94fead53e3ec2e7..1bb9238caebc0de8e753047f85a064f98becd1ce 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2009, 2010, 2011 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
@@ -280,6 +280,12 @@ test_insert (void)
   unsigned int init_pat;
   int i, j;
 
+#if __GNUC__ == 4 && __GNUC_MINOR__ == 2 && __llvm__
+  /* This test seems to trigger a bug in llvm-gcc 4.2 on Mac OS X 10.8.0.
+     Exit code 77 tells the Autotest framework that the test was skipped. */
+  exit (77);
+#endif
+
   for (init_pat = 0; init_pat < (1u << positions); init_pat++)
     for (i = 0; i < positions + 1; i++)
       for (j = i; j <= positions + 1; j++)
@@ -307,6 +313,12 @@ test_delete (void)
   unsigned int init_pat;
   int i, j;
 
+#if __GNUC__ == 4 && __GNUC_MINOR__ == 2 && __llvm__
+  /* This test seems to trigger a bug in llvm-gcc 4.2 on Mac OS X 10.8.0.
+     Exit code 77 tells the Autotest framework that the test was skipped. */
+  exit (77);
+#endif
+
   for (init_pat = 0; init_pat < (1u << positions); init_pat++)
     for (i = 0; i < positions + 1; i++)
       for (j = i; j <= positions + 1; j++)
@@ -331,6 +343,12 @@ test_allocate (void)
   unsigned int init_pat;
   int request;
 
+#if __GNUC__ == 4 && __GNUC_MINOR__ == 2 && __llvm__
+  /* This test seems to trigger a bug in llvm-gcc 4.2 on Mac OS X 10.8.0.
+     Exit code 77 tells the Autotest framework that the test was skipped. */
+  exit (77);
+#endif
+
   for (init_pat = 0; init_pat < (1u << positions); init_pat++)
     for (request = 1; request <= positions + 1; request++)
       {
@@ -381,6 +399,12 @@ test_allocate_fully (void)
   unsigned int init_pat;
   int request;
 
+#if __GNUC__ == 4 && __GNUC_MINOR__ == 2 && __llvm__
+  /* This test seems to trigger a bug in llvm-gcc 4.2 on Mac OS X 10.8.0.
+     Exit code 77 tells the Autotest framework that the test was skipped. */
+  exit (77);
+#endif
+
   for (init_pat = 0; init_pat < (1u << positions); init_pat++)
     for (request = 1; request <= positions + 1; request++)
       {
diff --git a/tests/libpspp/zip-test.c b/tests/libpspp/zip-test.c
new file mode 100644 (file)
index 0000000..7a2fcb1
--- /dev/null
@@ -0,0 +1,95 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2011 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/>. */
+
+
+/* A simple program to zip or unzip a file */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include "libpspp/assertion.h"
+#include <libpspp/compiler.h>
+#include <libpspp/zip-writer.h>
+#include <libpspp/zip-reader.h>
+#include <libpspp/str.h>
+
+#include "xalloc.h"
+\f
+/* Exit with a failure code.
+   (Place a breakpoint on this function while debugging.) */
+static void
+check_die (void)
+{
+  exit (EXIT_FAILURE);
+}
+
+int
+main (int argc, char **argv)
+{
+  if ( argc < 4)
+    {
+      fprintf (stderr, "Usage zip-test: {r|w} archive file0 file1 ... filen\n");
+      check_die ();
+    }
+
+  if ( 0 == strcmp ("w", argv[1]))
+    {
+      int i;
+      struct zip_writer *zw = zip_writer_create (argv[2]);
+      for (i = 3; i < argc; ++i)
+       {
+         FILE *fp = fopen (argv[i], "r");
+         if (!fp ) check_die ();
+         zip_writer_add (zw, fp, argv[i]);
+       }
+      zip_writer_close (zw);
+    }
+  else if ( 0  == strcmp ("r", argv[1]))
+    {
+      const int BUFSIZE=256;
+      char buf[BUFSIZE];
+      int i;
+      struct string str;
+      struct zip_reader *zr = zip_reader_create (argv[2], &str);
+      for (i = 3; i < argc; ++i)
+       {
+         int x = 0;
+         struct zip_member *zm = zip_member_open (zr, argv[i]);
+         FILE *fp = fopen (argv[i], "w");
+
+         while ((x = zip_member_read (zm, buf, BUFSIZE)) > 0)
+           {
+             fwrite (buf, x, 1, fp);
+           }
+         fclose (fp);
+         if ( x < 0)
+           {
+             fprintf (stderr, "Unzip failed: %s", ds_cstr (&str));
+             check_die ();
+           }
+         
+         zip_member_unref (zm);
+       }
+      zip_reader_destroy (zr);
+    }
+  else 
+    exit (1);
+
+  return 0;
+}
diff --git a/tests/libpspp/zip.at b/tests/libpspp/zip.at
new file mode 100644 (file)
index 0000000..55bf563
--- /dev/null
@@ -0,0 +1,43 @@
+AT_BANNER([zip])
+
+AT_SETUP([Basic zip - unzip test])
+AT_KEYWORDS([compression])
+
+AT_CHECK([dnl
+here=`pwd`
+dir1=$here/original
+dir2=$here/recovered
+
+mkdir -p $dir1
+
+# Generate files of differing sizes with random data in them
+names=""
+s=1;
+while test $s -le 8192 ; do
+       name=$dir1/$s
+       dd if=/dev/urandom of=$name count=1 bs=$s 2> /dev/null
+       s=$(($s * 2));
+       bn=`basename $name`;
+        names="$names $bn";
+done
+
+(cd $dir1 && $abs_top_builddir/tests/libpspp/zip-test w foo.zip $names)
+
+
+mkdir -p $dir2
+cp $dir1/foo.zip $dir2
+cd $dir2 
+$abs_top_builddir/tests/libpspp/zip-test r foo.zip $names
+
+# Compare the files to their originals
+for f in $names; do
+ diff $dir1/$f $dir2/$f;
+ if test $? -ne 0 ; then exit 1; fi;
+done
+
+exit 0
+])
+
+
+AT_CLEANUP
+
index 308dd7711b219a317b0f09f0470fe523f10dc9f2..b24278b7fc93b49050baaefe9d9adec6ccf3cb9c 100644 (file)
@@ -5,8 +5,12 @@ dnl built (with "make") but before it has been installed.  The -I options are
 dnl equivalent to "use ExtUtils::testlib;" inside the Perl program, but it does
 dnl not need to be run with the perl-module build directory as the current
 dnl working directory.
+dnl
+dnl XXX "libtool --mode=execute" is probably better than setting
+dnl LD_LIBRARY_PATH.
 m4_define([RUN_PERL_MODULE],
   [LD_LIBRARY_PATH=$abs_top_builddir/src/.libs \
+   DYLD_LIBRARY_PATH=$abs_top_builddir/src/.libs \
    $PERL -I$abs_top_builddir/perl-module/blib/arch \
          -I$abs_top_builddir/perl-module/blib/lib])
 
@@ -701,7 +705,7 @@ AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
 # Skip this test if Perl's Text::Diff module is not installed.
 AT_CHECK([perl -MText::Diff -e '' || exit 77])
 AT_CHECK([RUN_PERL_MODULE $abs_top_builddir/perl-module/t/Pspp.t], [0],
-  [[1..36
+  [[1..37
 ok 1 - use PSPP;
 ok 2 - Dictionary Creation
 ok 3
@@ -739,15 +743,6 @@ ok 33 - Missing Value Positive
 ok 34 - Missing Value Positive SYS
 ok 35 - Missing Value Positive Num
 ok 36 - Custom Attributes
-]],
-  [[# @&t@
-# @@ -0,0 +1 @@
-# +
-# @@ -0,0 +1 @@
-# +
-# @@ -0,0 +1 @@
-# +
-# @@ -0,0 +1 @@
-# +
-]])
+ok 37 - Case count
+]],[ignore])
 AT_CLEANUP