Merge commit 'origin/stable' build40
authorJohn Darrington <john@darrington.wattle.id.au>
Thu, 24 Sep 2009 18:43:42 +0000 (20:43 +0200)
committerJohn Darrington <john@darrington.wattle.id.au>
Thu, 24 Sep 2009 18:43:42 +0000 (20:43 +0200)
Conflicts:

AUTHORS
NEWS
configure.ac
lib/gtksheet/gtkitementry.c
po/LINGUAS
po/nl.po
src/data/file-name.c
src/data/sys-file-writer.c
src/language/stats/crosstabs.q
src/language/stats/examine.q
src/language/stats/t-test.q
src/output/charts/box-whisker.c
src/output/charts/plot-hist.c
src/ui/gui/output-viewer.c
src/ui/gui/psppire.c
src/ui/gui/psppire.h
src/ui/terminal/main.c

14 files changed:
1  2 
AUTHORS
NEWS
po/automake.mk
src/data/file-name.c
src/data/sys-file-writer.c
src/language/stats/examine.q
src/language/stats/regression.q
src/language/stats/t-test.q
src/output/charts/box-whisker.c
src/output/charts/plot-chart.h
src/output/charts/plot-hist.c
src/ui/gui/psppire.c
src/ui/gui/psppire.h
src/ui/terminal/main.c

diff --cc AUTHORS
Simple merge
diff --cc NEWS
index df10031e1d6221403902643e9ffa63cd2a535673,61a493863d439685a6e722212e9e90233ba43cad..1798fdd3c28d8021df00c9076ea59f5e2b262c72
--- 1/NEWS
--- 2/NEWS
+++ b/NEWS
@@@ -5,27 -5,91 +5,113 @@@ See the end for copying conditions
  
  Please send PSPP bug reports to bug-gnu-pspp@gnu.org.
  
- Changes from 0.6.1 to 0.7.0:
 +Changes from 0.7.1 to 0.7.2:
 +
 + * Updated Perl module interface.
 +
 + * Value labels for long string variables are now supported.
 +
 + * Missing values for long string variables are now supported.
 +
 +Changes from 0.7.0 to 0.7.1:
 +
 + *  Added a perl module to facilitate reading and writing of pspp system 
 +    files from perl programs.
 +
++Changes from 0.6.2-pre6 to 0.7.0:
 +
 +  * Custom variable and data file attributes are now supported.
 +    Commands VARIABLE ATTRIBUTE and DATAFILE ATTRIBUTE have been added
 +    for setting and clear attributes.  Support for attributes has also
 +    been added to commands that read and write system files, such as
 +    SAVE and GET, as well as to the DISPLAY command.
 +
+ Changes from 0.6.1 to 0.6.2-pre6:
+   * New translations:
+     - Dutch, thanks to Harry Thijssen.
+     - Brazilian Portuguese, thanks to Michel Boaventura.
+     Thanks for translations are also due to the coordinators at
+     translationproject.org.
+   * Statistical bug fixes:
+     - REGRESSION: Report correct standard error of the estimate (bug
+       #25677).
+     - T-TEST: Report correct significance of paired sample T-test in
+       the common case (bug #26936) and corner cases.  Thanks to Mike
+       Griffiths and Matej Cepl for reporting these bugs.
+   * Build fixes and changes:
+     - Make running "make" after running "configure" with different
+       settings reliably rebuild version.c.
+     - Cygwin and MinGW build fixes.
+     - Fixes for building with recent gnulib.
+     - The Makefile now honors two new variables, PSPP_LDFLAGS and
+       PSPPIRE_LDFLAGS, that affect linking of the PSPP and PSPPIRE
+       binaries, respectively.  This makes building easier for some
+       packagers.
+     - Fixes for "configure --enable-relocatable" (bug #25508).
+   * Data file bug fixes and changes:
+     - Fix reading text data files that contain a mix of white space
+       and commas.  Now "a ,b" is treated as two fields containing "a"
+       and "b"; previously it was treated as three, with an empty field
+       in the middle.
+     - Fix writing corrupted .sav files on Windows.
+     - Fix writing corrupted .por files (bug #26034).
+     - Fix reading .por files whose initial lines are not padded out
+       with spaces as expected.
+     - PSPP will no longer issue warnings about some .sav file records
+       or values that it does not understand.  These warnings were
+       harmless, but needlessly alarmed some users.
+     - Fix crash reading empty string fields from PostgreSQL databases.
+   * Bug fixes that affect PSPP and PSPPIRE:
+     - Users may now control precision of output statistics.  Instead
+       of hard coding the width and decimals of output numbers, respect
+       the default format in most instances.  Counts are now normally
+       displayed with the format of the weight variable, if any.
+     - Fix crash when an INSERT command specifies the name of a file
+       that does not exist (bug #24569).
+     - Fix crash when CROSSTABS specifies a long-string variable (bugs
+       #24557 and #26131).
+     - Fix crash drawing pie charts with many segments.
+     - Fix crash when NUMERIC specifies an invalid format.
+   * PSPPIRE bug fixes and changes:
+     - On Windows, write the output file to the user's home directory
+       instead of the current directory, to better match user
+       expectations.
+     - Some data editor fixes.
+   * Documentation:
+     - Fix typo in BINOMIAL section of user manual (bug #25892).
++>>>>>>> origin/stable:NEWS
  Changes from 0.6.0 to 0.6.1:
  
    * Statistical bug fixes:
diff --cc po/automake.mk
index 1f5ca31bd0b1c3607586d7d5bdc0cc4895a102ea,0000000000000000000000000000000000000000..56715e1ebdc8c8acb5834e56f28c2b2c893987a9
mode 100644,000000..100644
--- /dev/null
@@@ -1,54 -1,0 +1,54 @@@
- POFILES=po/en_GB.po po/nl.po
 +include $(top_srcdir)/po/Makevars
 +
 +XGETTEXT=xgettext
 +MSGMERGE=msgmerge
 +MSGFMT=msgfmt
 +
++POFILES=po/en_GB.po po/nl.po po/pt_BR.po
 +
 +POTFILE=po/$(DOMAIN).pot
 +
 +TRANSLATABLE_FILES = $(DIST_SOURCES) $(all_q_sources)
 +
 +$(POTFILE): $(TRANSLATABLE_FILES)
 +      @$(MKDIR_P) po
 +      $(XGETTEXT) --directory=$(top_srcdir) $(TRANSLATABLE_FILES) \
 +      $(XGETTEXT_OPTIONS) \
 +      --copyright-holder="$(COPYRIGHT_HOLDER)" \
 +      --package-name=$(PACKAGE) \
 +      --package-version=$(VERSION) \
 +      --msgid-bugs-address=$(MSGID_BUGS_ADDRESS) \
 +      --add-comments='TRANSLATORS:' \
 +      -o $(POTFILE)
 +
 +
 +$(POFILES): $(POTFILE)
 +      $(MSGMERGE) $(top_srcdir)/$* $< -o $@
 +
 +.po.gmo:
 +      @$(MKDIR_P) `dirname $@`
 +      $(MSGFMT) $< -o $@
 +
 +
 +GMOFILES = $(POFILES:.po=.gmo)
 +
 +ALL_LOCAL += $(GMOFILES)
 +
 +install-data-hook: $(GMOFILES)
 +      for f in $(GMOFILES); do \
 +        lang=`echo $$f | sed -e 's%po/\(.*\)\.gmo%\1%' ` ; \
 +        $(INSTALL) -D $$f $(DESTDIR)$(prefix)/share/locale/$$lang/LC_MESSAGES/$(DOMAIN).mo ; \
 +      done
 +      
 +
 +uninstall-hook:
 +      for f in $(GMOFILES); do \
 +        lang=`echo $$f | sed -e 's%po/\(.*\)\.gmo%\1%' ` ; \
 +        $(RM) $(DESTDIR)$(prefix)/share/locale/$$lang/LC_MESSAGES/$(DOMAIN).mo ; \
 +      done
 +
 +
 +EXTRA_DIST += $(POFILES) $(POTFILE)
 +
 +CLEANFILES += $(POFILES) $(GMOFILES) $(POTFILE)
 +
index 601afd5579e04a2ffff00193166989aedcd8e3b5,6be5ef0afa468b2705de8b95e88e328d8afca5c5..91229595924c7bfe7fe11d1486970ae598950f5c
@@@ -476,7 -476,7 +476,6 @@@ default_output_path (void
          const char *home_drive = getenv ("HOMEDRIVE");
          const char *home_path = getenv ("HOMEPATH");
  
--
          if (home_drive != NULL && home_path != NULL)
            home_dir = xasprintf ("%s%s",
                                  home_drive, home_path);
        if (home_dir == NULL)
        home_dir = "c:/users/default"; /* poor default */
  
-       path = xasprintf ("%s%c", home_dir, '/');
+       /* Copy home_dir into path.  Add a slash at the end but
+          only if there isn't already one there, because Windows
+          treats // specially. */
+       if (home_dir[0] == '\0'
+           || strchr ("/\\", home_dir[strlen (home_dir) - 1]) == NULL)
+         path = xasprintf ("%s%c", home_dir, '/');
+       else
+         path = xstrdup (home_dir);
  
 -
        for(i = 0; i < strlen (path); i++)
        if (path[i] == '\\') path[i] = '/';
      }
index 3fed2e05445135ec2ebcc300ce23c4855d0f41df,001b78f162a7d1724d73afba520f9066facbcfa4..5daea89dc5a908ac385a5f19dc8c2c62db7c0e20
@@@ -461,12 -435,11 +461,12 @@@ write_variable (struct sfm_writer *w, c
    /* Value label. */
    if (var_has_label (v))
      {
--      const char *label = var_get_label (v);
-       char *l = recode_string (dict_get_encoding (dict), UTF8, label, -1);
-       size_t padded_len = ROUND_UP (MIN (strlen (l), 255), 4);
-       write_int (w, padded_len);
-       write_string (w, l, padded_len);
-       free (l);
++      char *label = recode_string (dict_get_encoding (dict), UTF8, var_get_label (v), -1);
+       size_t label_len = MIN (strlen (label), 255);
+       size_t padded_len = ROUND_UP (label_len, 4);
+       write_int (w, label_len);
+       write_string (w, label, padded_len);
++      free (label);
      }
  
    /* Write the missing values, if any, range first. */
index e8333b1ceeaa5257d922b9be4700bc6aec8ef7d1,592bb56b13fa18d02279a6c50082f448e51849d5..08077942340234031939cded549e87886d5119ee
@@@ -1803,205 -1453,605 +1803,204 @@@ show_extremes (const struct variable **
           0, 0,
           n_cols - 1, n_rows - 1);
  
 -  tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
  
 -  tab_vline (tbl, TAL_1, heading_columns, 0, n_rows - 1);
 -  tab_vline (tbl, TAL_2, n_cols - 2, 0, n_rows - 1);
 +  tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
 +  tab_hline (tbl, TAL_2, 1, n_cols - 1, heading_rows );
    tab_vline (tbl, TAL_1, n_cols - 1, 0, n_rows - 1);
  
 -  tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE, _ ("Statistic"));
 -  tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, _ ("Std. Error"));
 +  if ( fctr->indep_var[0])
 +    tab_text (tbl, 1, 0, TAT_TITLE, var_to_string (fctr->indep_var[0]));
  
 -  tab_title (tbl, _ ("Descriptives"));
 +  if ( fctr->indep_var[1])
 +    tab_text (tbl, 2, 0, TAT_TITLE, var_to_string (fctr->indep_var[1]));
  
 -
 -  for ( i = 0 ; i < n_dep_var ; ++i )
 +  for (v = 0 ; v < n_dep_var ; ++v )
      {
 -      const int row = heading_rows + i * n_stat_rows * n_factors ;
 -
 -      if ( i > 0 )
 -      tab_hline (tbl, TAL_1, 0, n_cols - 1, row );
 +      struct ll *ll;
 +      int i = 0;
 +      const int row_var_start = v * cmd.st_n * 2 * ll_count(&fctr->result_list);
  
 -      tab_text (tbl, 0,
 -              i * n_stat_rows * n_factors  + heading_rows,
 +      tab_text (tbl,
 +              0,
 +              heading_rows + row_var_start,
                TAB_LEFT | TAT_TITLE,
 -              var_to_string (dependent_var[i])
 +              var_to_string (dependent_var[v])
                );
  
 -
 -      if ( fctr  )
 +      for (ll = ll_head (&fctr->result_list);
 +         ll != ll_null (&fctr->result_list); i++, ll = ll_next (ll))
        {
 -        const union value *prev = NULL;
 +        int e ;
 +        struct ll *min_ll;
 +        struct ll *max_ll;
 +        const int row_result_start = i * cmd.st_n * 2;
  
 -        struct factor_statistics **fs = fctr->fs;
 -        int count = 0;
 +        const struct factor_result *result =
 +          ll_data (ll, struct factor_result, ll);
  
 -        tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE,
 -                  var_to_string (fctr->indep_var[0]));
 +        if (i > 0 || v > 0)
 +          tab_hline (tbl, TAL_1, 1, n_cols - 1,
 +                     heading_rows + row_var_start + row_result_start);
  
 +        tab_hline (tbl, TAL_1, heading_columns - 2, n_cols - 1,
 +                   heading_rows + row_var_start + row_result_start + cmd.st_n);
  
 -        if ( fctr->indep_var[1])
 -          tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE,
 -                    var_to_string (fctr->indep_var[1]));
 -
 -        while ( *fs )
 +        for ( e = 1; e <= cmd.st_n; ++e )
            {
 -            const int row = heading_rows + n_stat_rows  *
 -               ( ( i  * n_factors  ) +  count );
 -
 -
 -            if ( !prev || 0 != compare_values (prev, (*fs)->id[0],
 -                                        var_get_width (fctr->indep_var[0])))
 -              {
 -                struct string vstr;
 -                ds_init_empty (&vstr);
 -                var_append_value_name (fctr->indep_var[0],
 -                                    (*fs)->id[0], &vstr);
 +            tab_text_format (tbl, n_cols - 3,
 +                               heading_rows + row_var_start + row_result_start + e - 1,
 +                               TAB_RIGHT,
 +                               "%d", e);
 +
 +            tab_text_format (tbl, n_cols - 3,
 +                               heading_rows + row_var_start + row_result_start + cmd.st_n + e - 1,
 +                               TAB_RIGHT,
 +                               "%d", e);
 +          }
  
 -                if ( count > 0 )
 -                  tab_hline (tbl, TAL_1, 1, n_cols - 1, row);
  
 -                tab_text (tbl,
 -                          1, row,
 -                          TAB_LEFT | TAT_TITLE,
 -                          ds_cstr (&vstr)
 -                          );
 +        min_ll = ll_head (extrema_list (result->metrics[v].minima));
 +        for (e = 0; e < cmd.st_n;)
 +          {
 +            struct extremum *minimum = ll_data (min_ll, struct extremum, ll);
 +            double weight = minimum->weight;
  
 -                ds_destroy (&vstr);
 +            while (weight-- > 0 && e < cmd.st_n)
 +              {
 +                tab_double (tbl, n_cols - 1,
 +                           heading_rows + row_var_start + row_result_start + cmd.st_n + e,
 +                           TAB_RIGHT,
 +                           minimum->value,
 +                           NULL);
 +
 +
 +                tab_fixed (tbl, n_cols - 2,
 +                           heading_rows + row_var_start +
 +                           row_result_start + cmd.st_n + e,
 +                           TAB_RIGHT,
 +                           minimum->location,
 +                           10, 0);
 +                ++e;
                }
  
 -            prev = (*fs)->id[0];
 +            min_ll = ll_next (min_ll);
 +          }
  
 -            if (fctr->indep_var[1] && count > 0 )
 -              tab_hline (tbl, TAL_1, 2, n_cols - 1, row);
 +        max_ll = ll_head (extrema_list (result->metrics[v].maxima));
 +        for (e = 0; e < cmd.st_n;)
 +          {
 +            struct extremum *maximum = ll_data (max_ll, struct extremum, ll);
 +            double weight = maximum->weight;
  
 -            if ( fctr->indep_var[1])
 +            while (weight-- > 0 && e < cmd.st_n)
                {
 -                struct string vstr;
 -                ds_init_empty (&vstr);
 -                var_append_value_name (fctr->indep_var[1], (*fs)->id[1], &vstr);
 -
 -              tab_text (tbl, 2, row,
 -                        TAB_LEFT | TAT_TITLE,
 -                          ds_cstr (&vstr)
 -                        );
 -
 -                ds_destroy (&vstr);
 +                tab_double (tbl, n_cols - 1,
 +                           heading_rows + row_var_start +
 +                            row_result_start + e,
 +                           TAB_RIGHT,
 +                           maximum->value,
 +                           NULL);
 +
 +
 +                tab_fixed (tbl, n_cols - 2,
 +                           heading_rows + row_var_start +
 +                           row_result_start + e,
 +                           TAB_RIGHT,
 +                           maximum->location,
 +                           10, 0);
 +                ++e;
                }
  
 -            populate_descriptives (tbl, heading_columns - 2,
 -                                   row,
 -                                   dependent_var[i],
 -                                   & (*fs)->m[i]);
 -
 -            count++ ;
 -            fs++;
 +            max_ll = ll_next (max_ll);
            }
  
 -      }
 -
 -      else
 -      {
 -
 -        populate_descriptives (tbl, heading_columns - 2,
 -                               i * n_stat_rows * n_factors  + heading_rows,
 -                               dependent_var[i],
 -                               &totals[i]);
 -      }
 -    }
 -
 -  tab_submit (tbl);
 -}
 -
 -
 -/* Fill in the descriptives data */
 -static void
 -populate_descriptives (struct tab_table *tbl, int col, int row,
 -                     const struct variable *var,
 -                     const struct metrics *m)
 -{
 -  const double t = gsl_cdf_tdist_Qinv ((1 - cmd.n_cinterval[0] / 100.0)/2.0,
 -                                     m->n -1);
 -
 -  tab_text (tbl, col,
 -          row,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Mean"));
 -
 -  tab_double (tbl, col + 2,
 -            row,
 -            TAB_CENTER,
 -            m->mean,
 -            NULL);
 -
 -  tab_double (tbl, col + 3,
 -            row,
 -            TAB_CENTER,
 -            m->se_mean,
 -            NULL);
 -
 -
 -  tab_text (tbl, col,
 -          row + 1,
 -          TAB_LEFT | TAT_TITLE | TAT_PRINTF,
 -          _ ("%g%% Confidence Interval for Mean"), cmd.n_cinterval[0]);
 -
 -
 -  tab_text (tbl, col + 1,
 -          row  + 1,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Lower Bound"));
 -
 -  tab_double (tbl, col + 2,
 -            row + 1,
 -            TAB_CENTER,
 -            m->mean - t * m->se_mean,
 -            NULL);
 -
 -  tab_text (tbl, col + 1,
 -          row + 2,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Upper Bound"));
 -
 -
 -  tab_double (tbl, col + 2,
 -            row + 2,
 -            TAB_CENTER,
 -            m->mean + t * m->se_mean,
 -            NULL);
 -
 -  tab_text (tbl, col,
 -          row + 3,
 -          TAB_LEFT | TAT_TITLE | TAT_PRINTF,
 -          _ ("5%% Trimmed Mean"));
 -
 -  tab_double (tbl, col + 2,
 -            row + 3,
 -            TAB_CENTER,
 -            m->trimmed_mean,
 -            NULL);
 -
 -  tab_text (tbl, col,
 -          row + 4,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Median"));
 -
 -  {
 -    struct percentile *p;
 -    double d = 50;
 -
 -    p = hsh_find (m->ptile_hash, &d);
 -
 -    assert (p);
 -
 -
 -    tab_double (tbl, col + 2,
 -              row + 4,
 -              TAB_CENTER,
 -              p->v,
 -              NULL);
 -  }
 -
 -
 -  tab_text (tbl, col,
 -          row + 5,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Variance"));
 -
 -  tab_double (tbl, col + 2,
 -            row + 5,
 -            TAB_CENTER,
 -            m->var,
 -            NULL);
 -
 -
 -  tab_text (tbl, col,
 -          row + 6,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Std. Deviation"));
 -
 -
 -  tab_double (tbl, col + 2,
 -            row + 6,
 -            TAB_CENTER,
 -            m->stddev,
 -            NULL);
 -
 -
 -  tab_text (tbl, col,
 -          row + 7,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Minimum"));
 -
 -  tab_double (tbl, col + 2,
 -            row + 7,
 -            TAB_CENTER,
 -            m->min, var_get_print_format (var));
 -
 -  tab_text (tbl, col,
 -          row + 8,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Maximum"));
 -
 -  tab_double (tbl, col + 2,
 -            row + 8,
 -            TAB_CENTER,
 -            m->max, var_get_print_format (var));
 -
 -  tab_text (tbl, col,
 -          row + 9,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Range"));
 -
 -
 -  tab_double (tbl, col + 2,
 -            row + 9,
 -            TAB_CENTER,
 -            m->max - m->min,
 -            NULL);
 -
 -  tab_text (tbl, col,
 -          row + 10,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Interquartile Range"));
 -
 -  {
 -    struct percentile *p1;
 -    struct percentile *p2;
 -
 -    double d = 75;
 -    p1 = hsh_find (m->ptile_hash, &d);
 -
 -    d = 25;
 -    p2 = hsh_find (m->ptile_hash, &d);
 -
 -    assert (p1);
 -    assert (p2);
 -
 -    tab_double (tbl, col + 2,
 -              row + 10,
 -              TAB_CENTER,
 -              p1->v - p2->v,
 -              NULL);
 -  }
 -
 -  tab_text (tbl, col,
 -          row + 11,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Skewness"));
 -
 -
 -  tab_double (tbl, col + 2,
 -            row + 11,
 -            TAB_CENTER,
 -            m->skewness,
 -            NULL);
 -
 -  /* stderr of skewness */
 -  tab_double (tbl, col + 3,
 -            row + 11,
 -            TAB_CENTER,
 -            calc_seskew (m->n),
 -            NULL);
 -
 -  tab_text (tbl, col,
 -          row + 12,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Kurtosis"));
 -
 -
 -  tab_double (tbl, col + 2,
 -            row + 12,
 -            TAB_CENTER,
 -            m->kurtosis,
 -            NULL);
 -
 -  /* stderr of kurtosis */
 -  tab_double (tbl, col + 3,
 -            row + 12,
 -            TAB_CENTER,
 -            calc_sekurt (m->n),
 -            NULL);
 -}
 -
 -
 -
 -void
 -box_plot_variables (const struct factor *fctr,
 -                 const struct variable **vars, int n_vars,
 -                 const struct variable *id)
 -{
 -
 -  int i;
 -  struct factor_statistics **fs ;
 -
 -  if ( ! fctr )
 -    {
 -      box_plot_group (fctr, vars, n_vars, id);
 -      return;
 -    }
 -
 -  for ( fs = fctr->fs ; *fs ; ++fs )
 -    {
 -      struct string str;
 -      double y_min = DBL_MAX;
 -      double y_max = -DBL_MAX;
 -      struct chart *ch = chart_create ();
 -      if (ch == NULL)
 -        break;
 -
 -      ds_init_empty (&str);
 -      factor_to_string (fctr, *fs, 0, &str );
 -
 -      chart_write_title (ch, "%s", ds_cstr (&str));
 -
 -      for ( i = 0 ; i < n_vars ; ++i )
 -      {
 -        y_max = MAX (y_max, (*fs)->m[i].max);
 -        y_min = MIN (y_min, (*fs)->m[i].min);
 -      }
 -
 -      boxplot_draw_yscale (ch, y_max, y_min);
 -
 -      for ( i = 0 ; i < n_vars ; ++i )
 -      {
 -
 -        const double box_width = (ch->data_right - ch->data_left)
 -          / (n_vars * 2.0 ) ;
 -
 -        const double box_centre = ( i * 2 + 1) * box_width
 -          + ch->data_left;
 -
 -        boxplot_draw_boxplot (ch,
 -                             box_centre, box_width,
 -                             & (*fs)->m[i],
 -                             var_to_string (vars[i]));
  
 -
 -      }
 -
 -      chart_submit (ch);
 -      ds_destroy (&str);
 -    }
 -}
 -
 -
 -
 -/* Do a box plot, grouping all factors into one plot ;
 -   each dependent variable has its own plot.
 -*/
 -void
 -box_plot_group (const struct factor *fctr,
 -             const struct variable **vars,
 -             int n_vars,
 -             const struct variable *id UNUSED)
 -{
 -
 -  int i;
 -
 -  for ( i = 0 ; i < n_vars ; ++i )
 -    {
 -      struct factor_statistics **fs ;
 -      struct chart *ch;
 -
 -      ch = chart_create ();
 -      if (ch == NULL)
 -        break;
 -
 -      boxplot_draw_yscale (ch, totals[i].max, totals[i].min);
 -
 -      if ( fctr )
 -      {
 -        int n_factors = 0;
 -        int f=0;
 -        for ( fs = fctr->fs ; *fs ; ++fs )
 -          ++n_factors;
 -
 -        chart_write_title (ch, _ ("Boxplot of %s vs. %s"),
 -                          var_to_string (vars[i]), var_to_string (fctr->indep_var[0]) );
 -
 -        for ( fs = fctr->fs ; *fs ; ++fs )
 +        if ( fctr->indep_var[0])
            {
 -            struct string str;
 -            const double box_width = (ch->data_right - ch->data_left)
 -              / (n_factors * 2.0 ) ;
 -
 -            const double box_centre = ( f++ * 2 + 1) * box_width
 -              + ch->data_left;
 -
 -            ds_init_empty (&str);
 -            factor_to_string_concise (fctr, *fs, &str);
 +            struct string vstr;
 +            ds_init_empty (&vstr);
 +            var_append_value_name (fctr->indep_var[0],
 +                                   &result->value[0], &vstr);
 +
 +            tab_text (tbl, 1,
 +                      heading_rows + row_var_start + row_result_start,
 +                      TAB_LEFT,
 +                      ds_cstr (&vstr)
 +                      );
  
 -            boxplot_draw_boxplot (ch,
 -                                 box_centre, box_width,
 -                                 & (*fs)->m[i],
 -                                 ds_cstr (&str));
 -              ds_destroy (&str);
 +            ds_destroy (&vstr);
            }
 -      }
 -      else if ( ch )
 -      {
 -        const double box_width = (ch->data_right - ch->data_left) / 3.0;
 -        const double box_centre = (ch->data_right + ch->data_left) / 2.0;
  
 -        chart_write_title (ch, _ ("Boxplot"));
  
 -        boxplot_draw_boxplot (ch,
 -                             box_centre,    box_width,
 -                             &totals[i],
 -                             var_to_string (vars[i]) );
 +        tab_text (tbl, n_cols - 4,
 +                  heading_rows + row_var_start + row_result_start,
 +                  TAB_RIGHT,
 +                  _("Highest"));
  
 +        tab_text (tbl, n_cols - 4,
 +                  heading_rows + row_var_start + row_result_start + cmd.st_n,
 +                  TAB_RIGHT,
 +                  _("Lowest"));
        }
 -
 -      chart_submit (ch);
      }
 -}
 -
 -
 -/* Plot the normal and detrended normal plots for m
 -   Label the plots with factorname */
 -void
 -np_plot (const struct metrics *m, const char *factorname)
 -{
 -  int i;
 -  double yfirst=0, ylast=0;
 -
 -  /* Normal Plot */
 -  struct chart *np_chart;
 -
 -  /* Detrended Normal Plot */
 -  struct chart *dnp_chart;
 -
 -  /* The slope and intercept of the ideal normal probability line */
 -  const double slope = 1.0 / m->stddev;
 -  const double intercept = - m->mean / m->stddev;
 -
 -  /* Cowardly refuse to plot an empty data set */
 -  if ( m->n_data == 0 )
 -    return ;
 -
 -  np_chart = chart_create ();
 -  dnp_chart = chart_create ();
 -
 -  if ( !np_chart || ! dnp_chart )
 -    return ;
 -
 -  chart_write_title (np_chart, _ ("Normal Q-Q Plot of %s"), factorname);
 -  chart_write_xlabel (np_chart, _ ("Observed Value"));
 -  chart_write_ylabel (np_chart, _ ("Expected Normal"));
 -
 -
 -  chart_write_title (dnp_chart, _ ("Detrended Normal Q-Q Plot of %s"),
 -                  factorname);
 -  chart_write_xlabel (dnp_chart, _ ("Observed Value"));
 -  chart_write_ylabel (dnp_chart, _ ("Dev from Normal"));
 -
 -  yfirst = gsl_cdf_ugaussian_Pinv (m->wvp[0]->rank / ( m->n + 1));
 -  ylast =  gsl_cdf_ugaussian_Pinv (m->wvp[m->n_data-1]->rank / ( m->n + 1));
 -
 -
 -  {
 -    /* Need to make sure that both the scatter plot and the ideal fit into the
 -       plot */
 -    double x_lower = MIN (m->min, (yfirst - intercept) / slope) ;
 -    double x_upper = MAX (m->max, (ylast  - intercept) / slope) ;
 -    double slack = (x_upper - x_lower)  * 0.05 ;
 -
 -    chart_write_xscale (np_chart, x_lower - slack, x_upper + slack, 5);
 -
 -    chart_write_xscale (dnp_chart, m->min, m->max, 5);
 -
 -  }
  
 -  chart_write_yscale (np_chart, yfirst, ylast, 5);
 -
 -  {
 -    /* We have to cache the detrended data, beacause we need to
 -       find its limits before we can plot it */
 -    double *d_data = xnmalloc (m->n_data, sizeof *d_data);
 -    double d_max = -DBL_MAX;
 -    double d_min = DBL_MAX;
 -    for ( i = 0 ; i < m->n_data; ++i )
 -      {
 -      const double ns = gsl_cdf_ugaussian_Pinv (m->wvp[i]->rank / ( m->n + 1));
 +  tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
  
 -      chart_datum (np_chart, 0, m->wvp[i]->v.f, ns);
  
 -      d_data[i] = (m->wvp[i]->v.f - m->mean) / m->stddev  - ns;
 +  tab_title (tbl, _("Extreme Values"));
  
 -      if ( d_data[i] < d_min ) d_min = d_data[i];
 -      if ( d_data[i] > d_max ) d_max = d_data[i];
 -      }
 -    chart_write_yscale (dnp_chart, d_min, d_max, 5);
  
 -    for ( i = 0 ; i < m->n_data; ++i )
 -      chart_datum (dnp_chart, 0, m->wvp[i]->v.f, d_data[i]);
 +  tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE,
 +          _("Case Number"));
  
 -    free (d_data);
 -  }
  
 -  chart_line (np_chart, slope, intercept, yfirst, ylast , CHART_DIM_Y);
 -  chart_line (dnp_chart, 0, 0, m->min, m->max , CHART_DIM_X);
 +  tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE,
 +          _("Value"));
  
 -  chart_submit (np_chart);
 -  chart_submit (dnp_chart);
 +  tab_submit (tbl);
  }
  
 +#define PERCENTILE_ROWS 2
  
 -
 -
 -/* Show the percentiles */
 -void
 +static void
  show_percentiles (const struct variable **dependent_var,
 -               int n_dep_var,
 -               struct factor *fctr)
 +                int n_dep_var,
 +                const struct xfactor *fctr)
  {
 -  struct tab_table *tbl;
    int i;
 +  int v;
 +  int heading_columns = 2;
 +  int n_cols;
 +  const int n_percentiles = subc_list_double_count (&percentile_list);
 +  const int heading_rows = 2;
 +  struct tab_table *tbl;
  
 -  int n_cols, n_rows;
 -  int n_factors;
 -
 -  struct hsh_table *ptiles ;
 -
 -  int n_heading_columns;
 -  const int n_heading_rows = 2;
 -  const int n_stat_rows = 2;
 +  int n_rows ;
 +  n_rows = n_dep_var;
  
 -  int n_ptiles ;
 +  assert (fctr);
  
 -  if ( fctr )
 +  if ( fctr->indep_var[0] )
      {
 -      struct factor_statistics **fs = fctr->fs ;
 -      n_heading_columns = 3;
 -      n_factors = hsh_count (fctr->fstats);
 -
 -      ptiles = (*fs)->m[0].ptile_hash;
 +      heading_columns = 3;
  
        if ( fctr->indep_var[1] )
 -      n_heading_columns = 4;
 -    }
 -  else
 -    {
 -      n_factors = 1;
 -      n_heading_columns = 2;
 -
 -      ptiles = totals[0].ptile_hash;
 +      {
 +        heading_columns = 4;
 +      }
      }
  
 -  n_ptiles = hsh_count (ptiles);
 -
 -  n_rows = n_heading_rows + n_dep_var * n_stat_rows * n_factors;
 +  n_rows *= ll_count (&fctr->result_list) * PERCENTILE_ROWS;
 +  n_rows += heading_rows;
  
 -  n_cols = n_heading_columns + n_ptiles ;
 +  n_cols = heading_columns + n_percentiles;
  
    tbl = tab_create (n_cols, n_rows, 0);
 +  tab_headers (tbl, heading_columns, 0, heading_rows, 0);
  
 -  tab_headers (tbl, n_heading_columns + 1, 0, n_heading_rows, 0);
 -
 -  tab_dim (tbl, tab_natural_dimensions);
 +  tab_dim (tbl, tab_natural_dimensions, NULL);
  
 -  /* Outline the box and have no internal lines*/
 +  /* Outline the box */
    tab_box (tbl,
           TAL_2, TAL_2,
           -1, -1,
Simple merge
index d25477cdd153f27a55b8170f89bdf75e6020b75a,ba7e9388a95274560589d30605ce2be3e0720718..c448d52ea035c3d163bef9bf343a8d6b9609f904
@@@ -47,8 -45,7 +47,9 @@@
  #include <output/table.h>
  #include <data/format.h>
  
++#include "minmax.h"
  #include "xalloc.h"
 +#include "xmemdup0.h"
  
  #include "gettext.h"
  #define _(msgid) gettext (msgid)
@@@ -1091,40 -1411,49 +1092,44 @@@ pscbox (struct t_test_proc *proc
  
    struct tab_table *table;
  
 -  table = tab_create (cols,rows,0);
 +  table = tab_create (cols, rows, 0);
  
    tab_columns (table, SOM_COL_DOWN, 1);
 -  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_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_dim (table, tab_natural_dimensions);
 -  tab_title (table, _ ("Paired Samples Correlations"));
 +  tab_dim (table, tab_natural_dimensions, NULL);
 +  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."));
 +  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 < n_pairs; ++i)
 +  for (i = 0; i < proc->n_pairs; i++)
      {
 -      double p,q;
 -
 -      double df = pairs[i].n -2;
 +      struct pair *pair = &proc->pairs[i];
++      double df = pair->n - 2;
 +      double p, q;
-       double df = pair->n -2;
-       double correlation_t = (pair->correlation * sqrt (df) /
-                               sqrt (1 - pow2 (pair->correlation)));
+       /* corr2 will mathematically always be in the range [0, 1.0].  Inaccurate
+          calculations sometimes cause it to be slightly greater than 1.0, so
+          force it into the correct range to avoid NaN from sqrt(). */
 -      double corr2 = MIN (1.0, pow2 (pairs[i].correlation));
 -      double correlation_t =
 -      pairs[i].correlation * sqrt (df) /
 -      sqrt (1 - corr2);
 -
++      double corr2 = MIN (1.0, pow2 (pair->correlation));
++      double correlation_t = pair->correlation * sqrt (df) / sqrt (1 - corr2);
  
        /* row headings */
 -      tab_text (table, 0,i+1, TAB_LEFT | TAT_TITLE | TAT_PRINTF,
 -             _ ("Pair %d"), i);
 -
 -      tab_text (table, 1,i+1, TAB_LEFT | TAT_TITLE | TAT_PRINTF,
 -             _ ("%s & %s"),
 -               var_get_name (pairs[i].v[0]),
 -               var_get_name (pairs[i].v[1]));
 -
 +      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, pairs[i].n, wfmt);
 -      tab_double (table, 3, i+1, TAB_RIGHT, pairs[i].correlation, NULL);
 +      tab_double (table, 2, i + 1, TAB_RIGHT, pair->n, &proc->weight_format);
 +      tab_double (table, 3, i + 1, TAB_RIGHT, pair->correlation, NULL);
  
        p = gsl_cdf_tdist_P (correlation_t, df);
        q = gsl_cdf_tdist_Q (correlation_t, df);
index c3641580e0511d66a0a293819c8b6f065a53f96d,8bcad4947eee31d63e09264daf960e0d0f8a1008..33c445b09a61b0ef36714272bd221bfd2cd9f741
@@@ -1,5 -1,5 +1,5 @@@
  /* PSPP - a program for statistical analysis.
-    Copyright (C) 2004, 2008 Free Software Foundation, Inc.
 -   Copyright (C) 2004, 2009 Free Software Foundation, Inc.
++   Copyright (C) 2004, 2008, 2009 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
@@@ -134,26 -182,37 +134,26 @@@ boxplot_draw_boxplot (struct chart *ch
             box_centre, box_bottom);
  
    /* (top half) */
 -  pl_fline_r(ch->lp,
 +  pl_fline_r (ch->lp,
             box_centre, top_whisker,
             box_centre, box_top);
 -  }
  
 -  /* Draw outliers */
 -  for ( i = 0 ; i < n_data ; ++i )
 +  outliers = box_whisker_outliers (bw);
 +  for (ll = ll_head (outliers);
 +       ll != ll_null (outliers); ll = ll_next (ll))
      {
 -      if ( wvp[i]->v.f >= hinge[2] + step )
 -      draw_outlier(ch, box_centre, wvp, i,
 -                   ( wvp[i]->v.f > hinge[2] + 2 * step )
 -                   );
 -
 -      if ( wvp[i]->v.f <= hinge[0] - step )
 -      draw_outlier(ch, box_centre, wvp, i,
 -                   ( wvp[i]->v.f < hinge[0] - 2 * step )
 -                   );
 +      const struct outlier *outlier = ll_data (ll, struct outlier, ll);
 +      draw_case (ch, box_centre, outlier);
      }
  
 -
    /* Draw  tick  mark on x axis */
-   draw_tick(ch, TICK_ABSCISSA, box_centre - ch->data_left, name);
+   draw_tick(ch, TICK_ABSCISSA, box_centre - ch->data_left, "%s", name);
  
    pl_restorestate_r(ch->lp);
 -
  }
  
 -
 -
  void
 -boxplot_draw_yscale(struct chart *ch , double y_max, double y_min)
 +boxplot_draw_yscale (struct chart *ch, double y_max, double y_min)
  {
    double y_tick;
    double d;
Simple merge
index 4b11618a2f1a409fa3d92a9071a456131ce8485a,88ad0899199d939dd5411cfb8fb2656368e395a4..fbf1925e635e165c3c096d119bace8123fa0d5bc
@@@ -97,14 -96,10 +97,10 @@@ hist_draw_bar (struct chart *ch, const 
                 x_pos, 0,
                 x_pos + width, height);
  
 -    pl_restorestate_r(ch->lp);
 +    pl_restorestate_r (ch->lp);
  
-     {
-       char buf[5];
-       snprintf (buf,5,"%g", (upper + lower) / 2.0);
-       draw_tick (ch, TICK_ABSCISSA,
-               x_pos + width / 2.0, buf);
-     }
+     draw_tick (ch, TICK_ABSCISSA,
+                x_pos + width / 2.0, "%g", (upper + lower) / 2.0);
    }
  }
  
index 3555463f88e4d353c84bcd366b223955d4217604,a7b22037b868e7d523726c8f80faab41ebe1acc8..1cd7ee803c736a740b373a53b035c7dcef6bd90a
@@@ -89,10 -75,14 +89,9 @@@ initialize (struct command_line_process
  {
    PsppireDict *dictionary = 0;
  
 -  /* gtk_init messes with the locale.
 -     So unset the bits we want to control ourselves */
 -  setlocale (LC_NUMERIC, "C");
 -
 -  bindtextdomain (PACKAGE, relocate (locale_dir));
--
 +  i18n_init ();
  
 -  glade_init ();
 +  preregister_widgets ();
  
    gsl_set_error_handler_off ();
    fn_init ();
index cfe49e9182aaa0f374eaec352e50e7c652d80cac,815de4a07eda818a77d77499b1900355148b2c95..27a633f2ecf35c57cd30dc01ac85aa4a61db28a9
  #ifndef PSPPIRE_H
  #define PSPPIRE_H
  
 +#include <argp.h>
  
 -void initialize (void);
 +struct command_line_processor ;
 +extern const struct argp non_option_argp ;
 +
 +void initialize (struct command_line_processor *, int argc, char **argv);
  void de_initialize (void);
++
 +void psppire_quit (void);
 +
  const char * output_file_name (void);
  
  #endif /* PSPPIRE_H */
index af8f7f2dd4df9828361a1dccfdb54d09473875b9,8acbdc2dde79d7bd1a8a97be24da76523bf0f928..7ad162fca6d40b746a0155d891d8e08784e2e4df
@@@ -166,6 -141,21 +167,7 @@@ main (int argc, char **argv
    return any_errors ();
  }
  \f
 -static void
 -i18n_init (void)
 -{
 -#if ENABLE_NLS
 -#if HAVE_LC_MESSAGES
 -  setlocale (LC_MESSAGES, "");
 -#endif
 -#if HAVE_LC_PAPER
 -  setlocale (LC_PAPER, "");
 -#endif
 -  bindtextdomain (PACKAGE, relocate (locale_dir));
 -  textdomain (PACKAGE);
 -#endif /* ENABLE_NLS */
 -}
  static void
  fpu_init (void)
  {