* Variable Display Parameter Record::
* Long Variable Names Record::
* Very Long String Record::
+* Character Encoding Record::
* Data File and Variable Attributes Records::
* Miscellaneous Informational Records::
* Dictionary Termination Record::
Machine endianness. 1 indicates big-endian, 2 indicates little-endian.
@item int32 character_code;
+@anchor{character-code}
Character code. 1 indicates EBCDIC, 2 indicates 7-bit ASCII, 3
indicates 8-bit ASCII, 4 indicates DEC Kanji.
Windows code page numbers are also valid.
+
+Experience has shown that in many files, this field is ignored or incorrect.
+For a more reliable indication of the file's character encoding
+see @ref{Character Encoding Record}.
@end table
@node Machine Floating-Point Info Record
The total length is @code{count} bytes.
@end table
+@node Character Encoding Record
+@section Character Encoding Record
+
+This record, if present, indicates the character encoding for string data,
+long variable names, variable labels, value labels and other strings in the
+file.
+
+@example
+/* @r{Header.} */
+int32 rec_type;
+int32 subtype;
+int32 size;
+int32 count;
+
+/* @r{Exactly @code{count} bytes of data.} */
+char encoding[];
+@end example
+
+@table @code
+@item int32 rec_type;
+Record type. Always set to 7.
+
+@item int32 subtype;
+Record subtype. Always set to 20.
+
+@item int32 size;
+The size of each element in the @code{encoding} member. Always set to 1.
+
+@item int32 count;
+The total number of bytes in @code{encoding}.
+
+@item char encoding[];
+The name of the character encoding. Normally this will be an official IANA characterset name or alias.
+See @url{http://www.iana.org/assignments/character-sets}.
+@end table
+
+This record is not present in files generated by older software.
+See also @ref{character-code}.
+
+
@node Data File and Variable Attributes Records
@section Data File and Variable Attributes Records
/COMPRESSION=@{ON,OFF@}
/SCOMPRESSION=@{ON,OFF@}
-(security)
+(miscellaneous)
/SAFER=ON
+ /LOCALE='string'
+
(obsolete settings accepted for compatibility, but ignored)
/BOXSTRING=@{'xxx','xxxxxxxxxxx'@}
overwrite files, for instance) but it is an improvement.
When set, this setting cannot be reset during the same session, for
obvious security reasons.
+
+@item LOCALE
+@cindex locale
+@cindex encoding, characters
+This item is used to set the default character encoding.
+The encoding may be specified either as an encoding name or alias
+(see @url{http://www.iana.org/assignments/character-sets}), or
+as a locale name.
+If given as a locale name, only the character encoding of the
+locale is relevant.
+
+System files written by PSPP will use this encoding.
+System files read by PSPP, for which the encoding is unknown, will be
+interpreted using this encoding.
+
+The full list of valid encodings and locale names/alias are operating system
+dependent.
+The following are all examples of acceptable syntax on common GNU/Linux
+systems.
+@example
+
+SET LOCALE='iso-8859-1'.
+
+SET LOCALE='ru_RU.cp1251'.
+
+SET LOCALE='japanese'.
+
+@end example
+
+Contrary to the intuition, this command does not affect any aspect
+of the system's locale.
@end table
@node SHOW
struct vector **vector; /* Vectors of variables. */
size_t vector_cnt; /* Number of vectors. */
struct attrset attributes; /* Custom attributes. */
+
+ char *encoding; /* Character encoding of string data */
+
const struct dict_callbacks *callbacks; /* Callbacks on dictionary
modification */
void *cb_data ; /* Data passed to callbacks */
void *changed_data;
};
+
+void
+dict_set_encoding (struct dictionary *d, const char *enc)
+{
+ if (enc)
+ d->encoding = strdup (enc);
+}
+
+const char *
+dict_get_encoding (const struct dictionary *d)
+{
+ return d->encoding ;
+}
+
+
void
dict_set_change_callback (struct dictionary *d,
void (*changed) (struct dictionary *, void*),
for (i = 0; i < s->vector_cnt; i++)
d->vector[i] = vector_clone (s->vector[i], s, d);
+ if ( s->encoding)
+ d->encoding = strdup (s->encoding);
+
dict_set_attributes (d, dict_get_attributes (s));
return d;
void dict_set_attributes (struct dictionary *, const struct attrset *);
bool dict_has_attributes (const struct dictionary *);
+
+void dict_set_encoding (struct dictionary *d, const char *enc);
+const char *dict_get_encoding (const struct dictionary *d);
+
+
/* Functions to be called upon dictionary changes. */
struct dict_callbacks
{
convert_xml_string_to_value (struct ccase *c, const struct variable *var,
const xmlChar *xv)
{
- char *text;
int n_bytes = 0;
union value *v = case_data_rw (c, var);
- text = recode_string (CONV_UTF8_TO_PSPP, (const char *) xv, -1);
+ const char *text = (const char *) xv;
if ( text)
n_bytes = MIN (var_get_width (var), strlen (text));
if ( errno != 0 || endptr == text)
v->f = SYSMIS;
}
-
- free (text);
}
struct var_spec
if ( r->node_type == XML_READER_TYPE_TEXT )
{
- char *text ;
xmlChar *value = xmlTextReaderValue (r->xtr);
-
- text = recode_string (CONV_UTF8_TO_PSPP, (const char *) value, -1);
+ const char *text = (const char *) value;
if ( r->row < r->start_row)
{
}
free (value);
- free (text);
}
else if ( r->node_type == XML_READER_TYPE_ELEMENT
&& r->state == STATE_CELL)
/* Create the dictionary and populate it */
*dict = r->dict = dict_create ();
+ dict_set_encoding (r->dict, (const char *) xmlTextReaderConstEncoding (r->xtr));
+
r->value_cnt = 0;
for (i = 0 ; i < n_var_specs ; ++i )
lex_is_id1 (char c_)
{
unsigned char c = c_;
- return isalpha (c) || c == '@' || c == '#' || c == '$';
+ return isalpha (c) || c == '@' || c == '#' || c == '$' || c >= 128;
}
lex_is_idn (char c_)
{
unsigned char c = c_;
- return lex_is_id1 (c) || isdigit (c) || c == '.' || c == '_';
+ return lex_is_id1 (c) || isdigit (c) || c == '.' || c == '_' || c >= 128;
}
/* Returns the length of the longest prefix of STRING that forms
/* Create the dictionary and populate it */
*dict = r->dict = dict_create ();
+ {
+ const int enc = PQclientEncoding (r->conn);
+
+ /* According to section 22.2 of the Postgresql manual
+ a value of zero (SQL_ASCII) indicates
+ "a declaration of ignorance about the encoding".
+ Accordingly, we don't set the dictionary's encoding
+ if we find this value.
+ */
+ if ( enc != 0 )
+ dict_set_encoding (r->dict, pg_encoding_to_char (enc));
+ }
+
/*
select count (*) from (select * from medium) stupid_sql_standard;
*/
-
ds_init_cstr (&query,
"BEGIN READ ONLY ISOLATION LEVEL SERIALIZABLE; "
"DECLARE pspp BINARY CURSOR FOR ");
#include "format.h"
#include "value.h"
#include "xalloc.h"
-#include <libpspp/i18n.h>
#include <libpspp/integer-format.h>
#include <libpspp/message.h>
+#include <libpspp/i18n.h>
#include "error.h"
{
init_viewport (width, length);
settings_set_epoch (-1);
- i18n_init ();
the_settings.styles = fmt_create ();
settings_set_decimal_char (get_system_decimal ());
settings_done (void)
{
fmt_done (the_settings.styles);
- i18n_done ();
}
/* Returns the floating-point format used for RB and RBHEX
case 20:
/* New in SPSS 16. Contains a single string that describes
the character encoding, e.g. "windows-1252". */
- break;
+ {
+ char *encoding = calloc (size, count + 1);
+ read_string (r, encoding, count + 1);
+ dict_set_encoding (dict, encoding);
+ return;
+ }
case 21:
/* New in SPSS 16. Encodes value labels for long string
static void write_longvar_table (struct sfm_writer *w,
const struct dictionary *dict);
+static void write_encoding_record (struct sfm_writer *w,
+ const struct dictionary *);
+
static void write_vls_length_table (struct sfm_writer *w,
const struct dictionary *dict);
write_data_file_attributes (w, d);
write_variable_attributes (w, d);
+ write_encoding_record (w, d);
+
/* Write end-of-headers record. */
write_int (w, 999);
write_int (w, 0);
ds_destroy (&map);
}
+
+static void
+write_encoding_record (struct sfm_writer *w,
+ const struct dictionary *d)
+{
+ const char *enc = dict_get_encoding (d);
+
+ if ( NULL == enc)
+ return;
+
+ write_int (w, 7); /* Record type. */
+ write_int (w, 20); /* Record subtype. */
+ write_int (w, 1); /* Data item (char) size. */
+ write_int (w, strlen (enc)); /* Number of data items. */
+ write_string (w, enc, strlen (enc));
+}
+
+
/* Writes the long variable name table. */
static void
write_longvar_table (struct sfm_writer *w, const struct dictionary *dict)
}
/* Writes null-terminated STRING in a field of the given WIDTH to
- W. If WIDTH is longer than WIDTH, it is truncated; if WIDTH
+ W. If STRING is longer than WIDTH, it is truncated; if WIDTH
is narrowed, it is padded on the right with spaces. */
static void
write_string (struct sfm_writer *w, const char *string, size_t width)
}
casereader_destroy (reader);
- t = tab_create (2, 10, 0);
+ t = tab_create (2, 11, 0);
tab_vline (t, TAL_GAP, 1, 0, 8);
tab_text (t, 0, 0, TAB_LEFT, _("File:"));
tab_text (t, 1, 0, TAB_LEFT, fh_get_file_name (h));
tab_text (t, 0, 9, TAB_LEFT, _("Mode:"));
tab_text (t, 1, 9, TAB_LEFT | TAT_PRINTF,
_("Compression %s."), info.compressed ? _("on") : _("off"));
+
+
+ tab_text (t, 0, 10, TAB_LEFT, _("Charset:"));
+ tab_text (t, 1, 10, TAB_LEFT | TAT_PRINTF,
+ dict_get_encoding(d) ? dict_get_encoding(d) : _("Unknown"));
+
+
tab_dim (t, tab_natural_dimensions);
tab_submit (t);
#include <libpspp/float-format.h>
#include <libpspp/integer-format.h>
#include <libpspp/message.h>
+#include <libpspp/i18n.h>
#include <math/random.h>
#include <output/journal.h>
#include <output/output.h>
journal=custom;
log=custom;
length=custom;
+ locale=custom;
listing=custom;
lowres=lores:auto/on/off;
lpi=integer "x>0" "%s must be greater than 0";
return 1;
}
+static int
+stc_custom_locale (struct lexer *lexer, struct dataset *ds UNUSED,
+ struct cmd_set *cmd UNUSED, void *aux UNUSED)
+{
+ const struct string *s;
+
+ lex_match (lexer, '=');
+
+ if ( !lex_force_string (lexer))
+ return 0;
+
+ s = lex_tokstr (lexer);
+
+ lex_get (lexer);
+
+ /* First try this string as an encoding name */
+ if ( valid_encoding (ds_cstr (s)))
+ set_default_encoding (ds_cstr (s));
+
+ /* Now try as a locale name (or alias) */
+ else if (set_encoding_from_locale (ds_cstr (s)))
+ {
+ }
+ else
+ {
+ msg (ME, _("%s is not a recognised encoding or locale name"),
+ ds_cstr (s));
+ return 0;
+ }
+
+ return 1;
+}
+
+
+
static int
stc_custom_seed (struct lexer *lexer, struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED)
{
msg (SN, _("LENGTH is %d."), settings_get_viewlength ());
}
+static void
+show_locale (const struct dataset *ds UNUSED)
+{
+ msg (SN, _("LOCALE is %s"), get_default_encoding ());
+}
+
static void
show_mxerrs (const struct dataset *ds UNUSED)
{
{"ERRORS", show_errors},
{"FORMAT", show_format},
{"LENGTH", show_length},
+ {"LOCALE", show_locale},
{"MXERRS", show_mxerrs},
{"MXLOOPS", show_mxloops},
{"MXWARNS", show_mxwarns},
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 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
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <libintl.h>
#include <iconv.h>
#include <errno.h>
#include "assertion.h"
+#include "hmapx.h"
+#include "hash-functions.h"
#include "i18n.h"
+#include "version.h"
+
#include <localcharset.h>
#include "xstrndup.h"
#include <langinfo.h>
#endif
-
-static char *locale;
-static char *charset;
-
-
-static iconv_t convertor[n_CONV];
-
+static char *default_encoding;
+static struct hmapx map;
/* A wrapper around iconv_open */
static iconv_t
create_iconv (const char* tocode, const char* fromcode)
{
- iconv_t conv = iconv_open (tocode, fromcode);
+ iconv_t conv;
+ struct hmapx_node *node;
+ size_t hash ;
+ char *key = alloca (strlen (tocode) + strlen (fromcode) + 2);
+
+ strcpy (key, tocode);
+ strcat (key, "\n"); /* hopefully no encoding names contain '\n' */
+ strcat (key, fromcode);
- /* I don't think it's safe to translate this string or to use messaging
- as the convertors have not yet been set up */
- if ( (iconv_t) -1 == conv && 0 != strcmp (tocode, fromcode))
+ hash = hsh_hash_string (key);
+
+ node = hmapx_first_with_hash (&map, hash);
+
+ if (!node)
+ {
+ conv = iconv_open (tocode, fromcode);
+
+ /* I don't think it's safe to translate this string or to use messaging
+ as the convertors have not yet been set up */
+ if ( (iconv_t) -1 == conv && 0 != strcmp (tocode, fromcode))
+ {
+ const int err = errno;
+ fprintf (stderr,
+ "Warning: "
+ "cannot create a convertor for \"%s\" to \"%s\": %s\n",
+ fromcode, tocode, strerror (err));
+ }
+
+ hmapx_insert (&map, conv, hash);
+ }
+ else
{
- const int err = errno;
- fprintf (stderr,
- "Warning: cannot create a convertor for \"%s\" to \"%s\": %s\n",
- fromcode, tocode, strerror (err));
+ conv = hmapx_node_data (node);
}
return conv;
The returned string must be freed when no longer required.
*/
char *
-recode_string (enum conv_id how, const char *text, int length)
+recode_string (const char *to, const char *from,
+ const char *text, int length)
{
char *outbuf = 0;
size_t outbufferlength;
char *op ;
size_t inbytes = 0;
size_t outbytes ;
+ iconv_t conv ;
/* FIXME: Need to ensure that this char is valid in the target encoding */
const char fallbackchar = '?';
if ( length == -1 )
length = strlen(text);
- assert (how < n_CONV);
- if (convertor[how] == (iconv_t) -1)
- return xstrndup (text, length);
+ if (to == NULL)
+ to = default_encoding;
+
+ if (from == NULL)
+ from = default_encoding;
for ( outbufferlength = 1 ; outbufferlength != 0; outbufferlength <<= 1 )
if ( outbufferlength > length)
outbytes = outbufferlength;
inbytes = length;
+
+ conv = create_iconv (to, from);
+
do {
const char *ip = text;
- result = iconv (convertor[how], (ICONV_CONST char **) &text, &inbytes,
+ result = iconv (conv, (ICONV_CONST char **) &text, &inbytes,
&op, &outbytes);
if ( -1 == result )
}
-/* Returns the current PSPP locale */
+void
+i18n_init (void)
+{
+#if ENABLE_NLS
+ setlocale (LC_CTYPE, "");
+#if HAVE_LC_MESSAGES
+ setlocale (LC_MESSAGES, "");
+#endif
+#if HAVE_LC_PAPER
+ setlocale (LC_PAPER, "");
+#endif
+ bindtextdomain (PACKAGE, locale_dir);
+ textdomain (PACKAGE);
+#endif /* ENABLE_NLS */
+
+ assert (default_encoding == NULL);
+ default_encoding = strdup (locale_charset ());
+
+ hmapx_init (&map);
+}
+
+
const char *
-get_pspp_locale (void)
+get_default_encoding (void)
{
- assert (locale);
- return locale;
+ return default_encoding;
}
-/* Set the PSPP locale */
void
-set_pspp_locale (const char *l)
+set_default_encoding (const char *enc)
{
- char *current_locale;
- char *current_charset;
+ free (default_encoding);
+ default_encoding = strdup (enc);
+}
- free(locale);
- locale = strdup(l);
- current_locale = strdup (setlocale (LC_CTYPE, 0));
- current_charset = strdup (locale_charset ());
- setlocale (LC_CTYPE, locale);
+/* Attempts to set the encoding from a locale name
+ returns true if successfull.
+ This function does not (should not!) alter the current locale.
+*/
+bool
+set_encoding_from_locale (const char *loc)
+{
+ bool ok = true;
+ char *c_encoding;
+ char *loc_encoding;
+ char *tmp = strdup (setlocale (LC_CTYPE, NULL));
- free (charset);
- charset = strdup (locale_charset ());
- setlocale (LC_CTYPE, current_locale);
+ setlocale (LC_CTYPE, "C");
+ c_encoding = strdup (locale_charset ());
- iconv_close (convertor[CONV_PSPP_TO_UTF8]);
- convertor[CONV_PSPP_TO_UTF8] = create_iconv ("UTF-8", charset);
+ setlocale (LC_CTYPE, loc);
+ loc_encoding = strdup (locale_charset ());
- iconv_close (convertor[CONV_SYSTEM_TO_PSPP]);
- convertor[CONV_SYSTEM_TO_PSPP] = create_iconv (charset, current_charset);
- iconv_close (convertor[CONV_UTF8_TO_PSPP]);
- convertor[CONV_UTF8_TO_PSPP] = create_iconv (charset, "UTF-8");
+ if ( 0 == strcmp (loc_encoding, c_encoding))
+ {
+ ok = false;
+ }
- free (current_locale);
- free (current_charset);
-}
-void
-i18n_init (void)
-{
- assert (!locale) ;
- locale = strdup (setlocale (LC_CTYPE, NULL));
+ setlocale (LC_CTYPE, tmp);
- setlocale (LC_CTYPE, locale);
+ free (tmp);
+
+ if (ok)
+ {
+ free (default_encoding);
+ default_encoding = loc_encoding;
+ }
+ else
+ free (loc_encoding);
- free (charset);
- charset = strdup (locale_charset ());
+ free (c_encoding);
- convertor[CONV_PSPP_TO_UTF8] = create_iconv ("UTF-8", charset);
- convertor[CONV_SYSTEM_TO_PSPP] = create_iconv (charset, charset);
- convertor[CONV_UTF8_TO_PSPP] = create_iconv (charset, "UTF-8");
+ return ok;
}
-
void
i18n_done (void)
{
- int i;
- free (locale);
- locale = 0;
+ struct hmapx_node *node;
+ iconv_t conv;
+ HMAPX_FOR_EACH (conv, node, &map)
+ iconv_close (conv);
- for(i = 0 ; i < n_CONV; ++i )
- {
- if ( (iconv_t) -1 == convertor[i] )
- continue;
- iconv_close (convertor[i]);
- }
+ hmapx_destroy (&map);
+
+ free (default_encoding);
+ default_encoding = NULL;
}
+bool
+valid_encoding (const char *enc)
+{
+ iconv_t conv = iconv_open ("UTF8", enc);
+
+ if ( conv == (iconv_t) -1)
+ return false;
+
+ iconv_close (conv);
+
+ return true;
+}
+
/* Return the system local's idea of the
decimal seperator character */
#ifndef I18N_H
#define I18N_H
-const char * get_pspp_locale (void);
-void set_pspp_locale (const char *locale);
-const char * get_pspp_charset (void);
+#include <stdbool.h>
void i18n_done (void);
void i18n_init (void);
-enum conv_id
- {
- CONV_PSPP_TO_UTF8,
- CONV_SYSTEM_TO_PSPP,
- CONV_UTF8_TO_PSPP,
- n_CONV
- };
+#define UTF8 "UTF-8"
+char * recode_string (const char *to, const char *from,
+ const char *text, int len);
-char * recode_string (enum conv_id how, const char *text, int len);
+bool valid_encoding (const char *enc);
/* Return the decimal separator according to the
system locale */
char get_system_decimal (void);
+const char * get_default_encoding (void);
+void set_default_encoding (const char *enc);
+
+bool set_encoding_from_locale (const char *loc);
+
+
#endif /* i18n.h */
#include "psppire-var-store.h"
#include "psppire-selector.h"
#include "dialog-common.h"
+#include <libpspp/i18n.h>
#include <language/expressions/public.h>
#include <language/syntax-string-source.h>
gtk_tree_path_free (path);
- name = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
+ name = recode_string (UTF8, psppire_dict_encoding (dict),
+ var_get_name (var),
+ -1);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dest));
#include <config.h>
+#include <libpspp/i18n.h>
#include "dialog-common.h"
#include "psppire-var-ptr.h"
var = get_selected_variable (tree_model, iter, dict);
- name = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
+ name = recode_string (UTF8, psppire_dict_encoding (dict),
+ var_get_name (var), -1);
g_object_set (cell, "text", name, NULL);
g_free (name);
}
#include "dict-display.h"
#include "psppire-dict.h"
+#include <libpspp/i18n.h>
#include "helper.h"
#include <data/variable.h>
#include <data/format.h>
gtk_tree_path_free (path);
- name = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
+ name = recode_string (UTF8, psppire_dict_encoding (PSPPIRE_DICT (dict)),
+ var_get_name (var), -1);
gtk_entry_set_text (GTK_ENTRY (dest), name);
g_free (name);
}
gtk_tree_path_free (path);
- name = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
+ name = recode_string (UTF8, psppire_dict_encoding (PSPPIRE_DICT (dict)),
+ var_get_name (var), -1);
result = ( 0 == strcmp (text, name));
g_free (name);
return GTK_WIDGET (get_object_assert (builder, name, GTK_TYPE_WIDGET));
}
-/* Converts a string in the pspp locale to utf-8.
- The return value must be freed when no longer required*/
-gchar *
-pspp_locale_to_utf8 (const gchar *text, gssize len, GError **err)
-{
- return recode_string (CONV_PSPP_TO_UTF8, text, len);
-}
-
-gchar *
-utf8_to_pspp_locale (const gchar *text, gssize len, GError **err)
-{
- return recode_string (CONV_UTF8_TO_PSPP, text, len);
-}
-
/* This function must be used whenever a filename generated by glib,
(eg, from gtk_file_chooser_get_filename) and passed to the C library,
(eg through a pspp syntax string).
GtkAction * get_action_assert (GtkBuilder *builder, const gchar *name);
GtkWidget * get_widget_assert (GtkBuilder *builder, const gchar *name);
-/* Converts a string in the pspp locale to utf-8 */
-gchar * pspp_locale_to_utf8 (const gchar *text, gssize len, GError **err);
-gchar * utf8_to_pspp_locale (const gchar *text, gssize len, GError **err);
-
gchar * convert_glib_filename_to_system_filename (const gchar *fname,
GError **err);
-
void connect_help (GtkBuilder *);
void reference_manual (GtkMenuItem *, gpointer);
set_program_name (argv[0]);
+ gtk_disable_setlocale ();
+
if ( ! gtk_parse_args (&argc, &argv) )
{
perror ("Error parsing arguments");
#include <language/syntax-string-source.h>
#include "psppire-data-store.h"
#include <ui/gui/sheet/psppire-axis-impl.h>
+#include <libpspp/i18n.h>
#include "helper.h"
#include <gtk-contrib/gtkxpaned.h>
gchar *text = g_strdup_printf ("%d: %s", row + FIRST_CASE_NUMBER,
var_get_name (var));
- gchar *s = pspp_locale_to_utf8 (text, -1, 0);
+ gchar *s = recode_string (UTF8,
+ psppire_dict_encoding (data_store->dict),
+ text, -1);
g_free (text);
#include <pango/pango-context.h>
#include "psppire-data-store.h"
+#include <libpspp/i18n.h>
#include "helper.h"
#include <data/dictionary.h>
if (label)
{
free (v);
- return pspp_locale_to_utf8 (label, -1, 0);
+ return recode_string (UTF8, psppire_dict_encoding (store->dict),
+ label, -1);
}
}
FP. No null terminator is appended to the buffer. */
data_out (v, fp, s->str);
- text = pspp_locale_to_utf8 (s->str, fp->w, 0);
+ text = recode_string (UTF8, psppire_dict_encoding (store->dict),
+ s->str, fp->w);
g_string_free (s, TRUE);
g_strchomp (text);
if (row == n_cases)
psppire_data_store_insert_new_case (store, row);
- s = utf8_to_pspp_locale (text, -1, NULL);
+ s = recode_string (psppire_dict_encoding (store->dict), UTF8, text, -1);
psppire_data_store_data_in (store, row,
var_get_case_index (pv), ss_cstr (s),
static gchar *
get_row_button_label (const PsppireSheetModel *model, gint unit)
{
+ PsppireDataStore *ds = PSPPIRE_DATA_STORE (model);
gchar *s = g_strdup_printf (_("%d"), unit + FIRST_CASE_NUMBER);
- gchar *text = pspp_locale_to_utf8 (s, -1, 0);
+ gchar *text = recode_string (UTF8, psppire_dict_encoding (ds->dict),
+ s, -1);
g_free (s);
if ( ! var_has_label (v))
return NULL;
- text = pspp_locale_to_utf8 (var_get_label (v), -1, 0);
+ text = recode_string (UTF8, psppire_dict_encoding (ds->dict),
+ var_get_label (v), -1);
return text;
}
pv = psppire_dict_get_variable (ds->dict, col);
- text = pspp_locale_to_utf8 (var_get_name (pv), -1, 0);
+ text = recode_string (UTF8, psppire_dict_encoding (ds->dict),
+ var_get_name (pv), -1);
return text;
}
#include <data/missing-values.h>
#include <data/value-labels.h>
#include <data/variable.h>
+#include <libpspp/i18n.h>
#include "helper.h"
#include "message-dialog.h"
{
case DICT_TVM_COL_NAME:
{
- gchar *name = pspp_locale_to_utf8(var_get_name (var), -1, NULL);
- g_value_init (value, G_TYPE_STRING);
- g_value_set_string (value, name);
- g_free (name);
+ gchar *name = recode_string (UTF8, psppire_dict_encoding (dict),
+ var_get_name (var), -1);
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, name);
+ g_free (name);
}
break;
case DICT_TVM_COL_VAR:
}
}
#endif
+
+
+
+
+const gchar *
+psppire_dict_encoding (const PsppireDict *dict)
+{
+ return dict_get_encoding (dict->dict);
+}
void psppire_dict_dump (const PsppireDict *);
#endif
+const gchar *psppire_dict_encoding (const PsppireDict *);
+
G_END_DECLS
#endif /* __PSPPIRE_DICT_H__ */
#include "psppire-dict.h"
#include "psppire-conf.h"
#include <data/format.h>
+#include <libpspp/i18n.h>
#include "helper.h"
#include <gettext.h>
)
{
*model = top_model;
- *iter = *top_iter;
+
+ if ( iter)
+ *iter = *top_iter;
while ( ! PSPPIRE_IS_DICT (*model))
{
- GtkTreeIter parent_iter = *iter;
+ GtkTreeIter parent_iter;
+ if (iter)
+ parent_iter = *iter;
if ( GTK_IS_TREE_MODEL_FILTER (*model))
{
*model = gtk_tree_model_filter_get_model (parent_model);
- gtk_tree_model_filter_convert_iter_to_child_iter (parent_model,
- iter,
- &parent_iter);
+ if (iter)
+ gtk_tree_model_filter_convert_iter_to_child_iter (parent_model,
+ iter,
+ &parent_iter);
}
else if (GTK_IS_TREE_MODEL_SORT (*model))
{
*model = gtk_tree_model_sort_get_model (parent_model);
- gtk_tree_model_sort_convert_iter_to_child_iter (parent_model,
- iter,
- &parent_iter);
+ if (iter)
+ gtk_tree_model_sort_convert_iter_to_child_iter (parent_model,
+ iter,
+ &parent_iter);
}
}
}
struct variable *var;
GtkTreeIter iter;
GtkTreeModel *model;
-
+ PsppireDict *dict;
dv_get_base_model (top_model, top_iter, &model, &iter);
- g_assert (PSPPIRE_IS_DICT (model));
+ dict = PSPPIRE_DICT (model);
gtk_tree_model_get (model,
&iter, DICT_TVM_COL_VAR, &var, -1);
"<span stretch=\"condensed\">%s</span>",
var_get_label (var));
- char *utf8 = pspp_locale_to_utf8 (text, -1, NULL);
+ char *utf8 = recode_string (UTF8, psppire_dict_encoding (dict),
+ text, -1);
g_free (text);
g_object_set (cell, "markup", utf8, NULL);
}
else
{
- char *name = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
+ char *name = recode_string (UTF8, psppire_dict_encoding (dict),
+ var_get_name (var), -1);
g_object_set (cell, "text", name, NULL);
g_free (name);
}
struct variable *var = NULL;
gboolean ok;
-
gtk_tree_view_convert_widget_to_bin_window_coords (treeview,
x, y, &bx, &by);
tree_model = gtk_tree_view_get_model (treeview);
-
gtk_tree_view_set_tooltip_row (treeview, tooltip, path);
ok = gtk_tree_model_get_iter (tree_model, &iter, path);
{
gchar *tip ;
+ GtkTreeModel *m;
+ PsppireDict *dict;
+
+ dv_get_base_model (tree_model, NULL, &m, NULL);
+ dict = PSPPIRE_DICT (m);
if ( PSPPIRE_DICT_VIEW (treeview)->prefer_labels )
- tip = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
+ tip = recode_string (UTF8, psppire_dict_encoding (dict),
+ var_get_name (var), -1);
else
- tip = pspp_locale_to_utf8 (var_get_label (var), -1, NULL);
+ tip = recode_string (UTF8, psppire_dict_encoding (dict),
+ var_get_label (var), -1);
gtk_tooltip_set_text (tooltip, tip);
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (vs));
- vs->val_labs_dialog = val_labs_dialog_create (GTK_WINDOW (toplevel));
+ vs->val_labs_dialog = val_labs_dialog_create (GTK_WINDOW (toplevel),
+ PSPPIRE_SHEET (vs));
vs->missing_val_dialog = missing_val_dialog_create (GTK_WINDOW (toplevel));
vs->var_type_dialog = var_type_dialog_create (GTK_WINDOW (toplevel));
#define _(msgid) gettext (msgid)
#define N_(msgid) msgid
-
+#include <libpspp/i18n.h>
#include <gobject/gvaluecollector.h>
static void psppire_var_store_finalize (GObject *object);
-gchar * missing_values_to_string (const struct variable *pv, GError **err);
-
-
static gchar *psppire_var_store_get_string (const PsppireSheetModel *sheet_model, glong row, glong column);
static gboolean psppire_var_store_clear (PsppireSheetModel *model, glong row, glong col);
static glong psppire_var_store_get_row_count (const PsppireSheetModel * model);
static glong psppire_var_store_get_column_count (const PsppireSheetModel * model);
-static gchar *text_for_column (const struct variable *pv, gint c, GError **err);
+static gchar *text_for_column (PsppireVarStore *vs, const struct variable *pv,
+ gint c, GError **err);
static GObjectClass *parent_class = NULL;
}
static gchar *
-psppire_var_store_get_string (const PsppireSheetModel *model, glong row, glong column)
+psppire_var_store_get_string (const PsppireSheetModel *model,
+ glong row, glong column)
{
PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
pv = psppire_dict_get_variable (store->dict, row);
- return text_for_column (pv, column, 0);
+ return text_for_column (store, pv, column, 0);
}
break;
case PSPPIRE_VAR_STORE_COL_LABEL:
{
- gchar *s = utf8_to_pspp_locale (text, -1, NULL);
+ gchar *s = recode_string (psppire_dict_encoding (var_store->dict),
+ UTF8,
+ text, -1);
var_set_label (pv, s);
free (s);
return TRUE;
static const gchar none[] = N_("None");
static gchar *
-text_for_column (const struct variable *pv, gint c, GError **err)
+text_for_column (PsppireVarStore *vs,
+ const struct variable *pv, gint c, GError **err)
{
+ PsppireDict *dict = vs->dict;
static const gchar *const type_label[] =
{
N_("Numeric"),
switch (c)
{
case PSPPIRE_VAR_STORE_COL_NAME:
- return pspp_locale_to_utf8 ( var_get_name (pv), -1, err);
+ return recode_string (UTF8, psppire_dict_encoding (dict),
+ var_get_name (pv), -1);
break;
case PSPPIRE_VAR_STORE_COL_TYPE:
{
}
break;
case PSPPIRE_VAR_STORE_COL_LABEL:
- return pspp_locale_to_utf8 (var_get_label (pv), -1, err);
+ return recode_string (UTF8, psppire_dict_encoding (dict),
+ var_get_label (pv), -1);
break;
case PSPPIRE_VAR_STORE_COL_MISSING:
{
- return missing_values_to_string (pv, err);
+ return missing_values_to_string (dict, pv, err);
}
break;
case PSPPIRE_VAR_STORE_COL_VALUES:
val_labs_done (&ip);
- ss = pspp_locale_to_utf8 (gstr->str, gstr->len, err);
+ ss = recode_string (UTF8, psppire_dict_encoding (dict),
+ gstr->str, gstr->len);
g_string_free (gstr, TRUE);
return ss;
}
#include <config.h>
-#include <locale.h>
+#include <libpspp/i18n.h>
#include <assert.h>
#include <libintl.h>
#include <gsl/gsl_errno.h>
{
PsppireDict *dictionary = 0;
- /* gtk_init messes with the locale.
- So unset the bits we want to control ourselves */
- setlocale (LC_NUMERIC, "C");
-
- bindtextdomain (PACKAGE, locale_dir);
+ i18n_init ();
preregister_widgets ();
message_dialog_done ();
settings_done ();
outp_done ();
+ i18n_done ();
}
/* PSPPIRE - a graphical user interface for PSPP.
- Copyright (C) 2005 Free Software Foundation
+ Copyright (C) 2005, 2009 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 "val-labs-dialog.h"
#include <data/value-labels.h>
#include <data/format.h>
-
+#include "psppire-var-sheet.h"
+#include "psppire-var-store.h"
+#include <libpspp/i18n.h>
struct val_labs_dialog
{
GtkWidget *window;
+ PsppireSheet *vs;
+
/* The variable to be updated */
struct variable *pv;
/* Callback which occurs when a line item is selected in the list of
value--label pairs.*/
static void
-on_select_row (GtkTreeView *treeview,
- gpointer data)
+on_select_row (GtkTreeView *treeview, gpointer data)
{
gchar *labeltext;
struct val_labs_dialog *dialog = data;
gchar *const text = value_to_text (vl->value,
*var_get_write_format (dialog->pv));
+ PsppireVarStore *var_store =
+ PSPPIRE_VAR_STORE (psppire_sheet_get_model (dialog->vs));
+
g_signal_handler_block (GTK_ENTRY (dialog->value_entry),
dialog->value_handler_id);
g_signal_handler_block (GTK_ENTRY (dialog->label_entry),
dialog->change_handler_id);
- labeltext = pspp_locale_to_utf8 (vl->label, -1, 0);
+
+ labeltext = recode_string (UTF8, psppire_dict_encoding (var_store->dict),
+ vl->label, -1);
+
gtk_entry_set_text (GTK_ENTRY (dialog->label_entry),
labeltext);
g_free (labeltext);
/* Create a new dialog box
(there should normally be only one)*/
struct val_labs_dialog *
-val_labs_dialog_create (GtkWindow *toplevel)
+val_labs_dialog_create (GtkWindow *toplevel, PsppireSheet *sheet)
{
GtkTreeViewColumn *column;
dialog->window = get_widget_assert (xml,"val_labs_dialog");
dialog->value_entry = get_widget_assert (xml,"value_entry");
dialog->label_entry = get_widget_assert (xml,"label_entry");
+ dialog->vs = sheet;
gtk_window_set_transient_for
(GTK_WINDOW (dialog->window), toplevel);
GtkTreeIter iter;
+ PsppireVarStore *var_store =
+ PSPPIRE_VAR_STORE (psppire_sheet_get_model (dialog->vs));
+
GtkListStore *list_store = gtk_list_store_new (2,
G_TYPE_STRING,
G_TYPE_DOUBLE);
*var_get_write_format (dialog->pv));
gchar *labeltext =
- pspp_locale_to_utf8 (vl->label, -1, 0);
+ recode_string (UTF8,
+ psppire_dict_encoding (var_store->dict),
+ vl->label, -1);
gchar *const text = g_strdup_printf ("%s = \"%s\"",
- vstr, labeltext);
-
+ vstr, labeltext);
gtk_list_store_append (list_store, &iter);
gtk_list_store_set (list_store, &iter,
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_LABS_DIALOG_H
#define __PSPPIRE_VAL_LABS_DIALOG_H
#include <gtk/gtk.h>
#include <data/variable.h>
+#include <gtk-contrib/psppire-sheet.h>
struct val_labs;
-struct val_labs_dialog * val_labs_dialog_create (GtkWindow *);
+struct val_labs_dialog * val_labs_dialog_create (GtkWindow *, PsppireSheet *);
void val_labs_dialog_show (struct val_labs_dialog *);
#include <data/variable.h>
#include <data/format.h>
#include <stdlib.h>
+#include "psppire-dict.h"
#include <gettext.h>
#define _(msgid) gettext (msgid)
#define N_(msgid) msgid
#include "helper.h"
+#include <libpspp/i18n.h>
static const gchar none[] = N_("None");
-gchar *
-name_to_string (const struct variable *var, GError **err)
-{
- const char *name = var_get_name (var);
- g_assert (name);
-
- return pspp_locale_to_utf8 (name, -1, err);
-}
-
-
-gchar *
-label_to_string (const struct variable *var, GError **err)
-{
- const char *label = var_get_label (var);
-
- if ( ! label ) return g_strdup (none);
-
- return pspp_locale_to_utf8 (label, -1, err);
-}
gchar *
measure_to_string (const struct variable *var, GError **err)
gchar *
-missing_values_to_string (const struct variable *pv, GError **err)
+missing_values_to_string (const PsppireDict *dict, const struct variable *pv, GError **err)
{
const struct fmt_spec *fmt = var_get_print_format (pv);
gchar *s;
g_string_append (gstr, mv[i]);
g_free (mv[i]);
}
- s = pspp_locale_to_utf8 (gstr->str, gstr->len, err);
+ s = recode_string (UTF8, psppire_dict_encoding (dict),
+ gstr->str, gstr->len);
g_string_free (gstr, TRUE);
}
else
g_string_append (gstr, ss);
free (ss);
}
- s = pspp_locale_to_utf8 (gstr->str, gstr->len, err);
+ s = recode_string (UTF8, psppire_dict_encoding (dict),
+ gstr->str, gstr->len);
g_string_free (gstr, TRUE);
}
#include <glib.h>
#include <data/variable.h>
+#include "psppire-dict.h"
struct variable;
#define n_ALIGNMENTS 3
extern const gchar *const alignments[n_ALIGNMENTS + 1];
-
extern const gchar *const measures[n_MEASURES + 1];
-
-gchar * name_to_string (const struct variable *var, GError **err);
-
-
-gchar * missing_values_to_string (const struct variable *pv, GError **err);
-
-gchar * measure_to_string (const struct variable *var, GError **err);
-
-gchar * label_to_string (const struct variable *var, GError **err);
-
+gchar *missing_values_to_string (const PsppireDict *dict, const struct variable *pv, GError **err);
+gchar *measure_to_string (const struct variable *var, GError **err);
#endif
#include "helper.h"
#include <language/syntax-string-source.h>
+#include <libpspp/i18n.h>
#include "helper.h"
#define N_(msgid) msgid
+static const gchar none[] = N_("None");
+
+
+static gchar *
+name_to_string (const struct variable *var, PsppireDict *dict)
+{
+ const char *name = var_get_name (var);
+ g_assert (name);
+
+ return recode_string (UTF8, psppire_dict_encoding (dict),
+ name, -1);
+}
+
+
+static gchar *
+label_to_string (const struct variable *var, PsppireDict *dict)
+{
+ const char *label = var_get_label (var);
+
+ if (! label) return g_strdup (none);
+
+ return recode_string (UTF8, psppire_dict_encoding (dict),
+ label, -1);
+}
+
static void
populate_text (PsppireDictView *treeview, gpointer data)
{
gchar *text = 0;
GString *gstring;
+ PsppireDict *dict;
- GtkTextBuffer *textbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(data));
+ GtkTextBuffer *textbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (data));
const struct variable *var =
psppire_dict_view_get_selected_variable (treeview);
if ( var == NULL)
return;
+ g_object_get (treeview,
+ "dictionary", &dict,
+ NULL);
+
gstring = g_string_sized_new (200);
- text = name_to_string (var, NULL);
+ text = name_to_string (var, dict);
g_string_assign (gstring, text);
g_free (text);
g_string_append (gstring, "\n");
- text = label_to_string (var, NULL);
+ text = label_to_string (var, dict);
g_string_append_printf (gstring, _("Label: %s\n"), text);
g_free (text);
g_string_append_printf (gstring, _("Type: %s\n"), buffer);
}
- text = missing_values_to_string (var, NULL);
+ text = missing_values_to_string (dict, var, NULL);
g_string_append_printf (gstring, _("Missing Values: %s\n"),
text);
g_free (text);
g_string_append (gstring, "\n");
g_string_append (gstring, _("Value Labels:\n"));
-#if 1
for (vl = val_labs_first_sorted (labs, &vli);
vl;
vl = val_labs_next (labs, &vli))
gchar *const vstr =
value_to_text (vl->value, *var_get_print_format (var));
- text = pspp_locale_to_utf8 (vl->label, -1, NULL);
+
+ text = recode_string (UTF8, psppire_dict_encoding (dict),
+ vl->label, -1);
g_string_append_printf (gstring, _("%s %s\n"), vstr, text);
g_free (text);
g_free (vstr);
}
-#endif
}
gtk_text_buffer_set_text (textbuffer, gstring->str, gstring->len);
#include <config.h>
-#include <locale.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <ieeefp.h>
#endif
+
+#include <libpspp/i18n.h>
#include <data/dictionary.h>
#include <data/file-handle-def.h>
#include <libpspp/getl.h>
#define _(msgid) gettext (msgid)
-static void i18n_init (void);
static void fpu_init (void);
static void clean_up (void);
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, locale_dir);
- textdomain (PACKAGE);
-#endif /* ENABLE_NLS */
-}
-
static void
fpu_init (void)
{
readln_uninitialize ();
outp_done ();
msg_ui_done ();
+ i18n_done ();
}
}
Type: System File.
Weight: Not weighted.
Mode: Compression on.
+Charset: Unknown
+--------+-------------+---+
|Variable|Description |Pos|
| | |iti|
size_t size, size_t count);
static void read_variable_attributes (struct sfm_reader *r,
size_t size, size_t count);
+static void read_character_encoding (struct sfm_reader *r,
+ size_t size, size_t count);
+
static struct text_record *open_text_record (
struct sfm_reader *, size_t size);
read_variable_attributes (r, size, count);
return;
+ case 20:
+ read_character_encoding (r, size, count);
+ return;
+
default:
sys_warn (r, _("Unrecognized record type 7, subtype %d."), subtype);
break;
close_text_record (text);
}
+static void
+read_character_encoding (struct sfm_reader *r, size_t size, size_t count)
+{
+ const unsigned long int posn = ftell (r->file);
+ char *encoding = calloc (size, count + 1);
+ read_string (r, encoding, count + 1);
+
+ printf ("%08lx: Character Encoding: %s\n", posn, encoding);
+}
+
+
static void
read_variable_attributes (struct sfm_reader *r, size_t size, size_t count)
{