1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2004, 2005, 2006, 2009, 2010, 2011, 2012, 2013 Free Software Foundation
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 #include <gsl/gsl_errno.h>
26 #include "data/any-reader.h"
27 #include "data/casereader.h"
28 #include "data/dataset.h"
29 #include "data/datasheet.h"
30 #include "data/file-handle-def.h"
31 #include "data/file-name.h"
32 #include "data/por-file-reader.h"
33 #include "data/session.h"
34 #include "data/settings.h"
35 #include "data/sys-file-reader.h"
37 #include "language/lexer/lexer.h"
38 #include "libpspp/i18n.h"
39 #include "libpspp/message.h"
40 #include "libpspp/version.h"
42 #include "output/driver.h"
43 #include "output/journal.h"
44 #include "output/message-item.h"
46 #include "ui/gui/dict-display.h"
47 #include "ui/gui/executor.h"
48 #include "ui/gui/psppire-data-store.h"
49 #include "ui/gui/psppire-data-window.h"
50 #include "ui/gui/psppire-dict.h"
51 #include "ui/gui/psppire.h"
52 #include "ui/gui/psppire-output-window.h"
53 #include "ui/gui/psppire-syntax-window.h"
54 #include "ui/gui/psppire-selector.h"
55 #include "ui/gui/psppire-var-view.h"
56 #include "ui/gui/psppire-window-register.h"
57 #include "ui/gui/widgets.h"
58 #include "ui/source-init-opts.h"
59 #include "ui/syntax-gen.h"
61 #include "ui/gui/icons/icon-names.h"
64 #include "gl/configmake.h"
65 #include "gl/xalloc.h"
66 #include "gl/relocatable.h"
68 static void inject_renamed_icons (void);
69 static void create_icon_factory (void);
70 static gchar *local_to_filename_encoding (const char *fn);
73 #define _(msgid) gettext (msgid)
74 #define N_(msgid) msgid
78 initialize (const char *data_file)
82 preregister_widgets ();
84 gsl_set_error_handler_off ();
88 psppire_set_lexer (NULL);
90 bind_textdomain_codeset (PACKAGE, "UTF-8");
92 inject_renamed_icons ();
93 create_icon_factory ();
95 psppire_output_window_setup ();
100 psppire_selector_set_default_selection_func (GTK_TYPE_ENTRY, insert_source_row_into_entry);
101 psppire_selector_set_default_selection_func (PSPPIRE_VAR_VIEW_TYPE, insert_source_row_into_tree_view);
102 psppire_selector_set_default_selection_func (GTK_TYPE_TREE_VIEW, insert_source_row_into_tree_view);
106 gchar *filename = local_to_filename_encoding (data_file);
108 /* Check to see if the file is a .sav or a .por file. If not
109 assume that it is a syntax file */
110 if ( any_reader_may_open (filename))
111 open_data_window (NULL, filename, NULL);
114 create_data_window ();
115 open_syntax_window (filename, NULL);
121 create_data_window ();
134 func (gpointer key, gpointer value, gpointer data)
137 PsppireWindow *window = PSPPIRE_WINDOW (value);
139 g_signal_emit_by_name (window, "delete-event", 0, &rv);
145 PsppireWindowRegister *reg = psppire_window_register_new ();
146 psppire_window_register_foreach (reg, func, NULL);
152 inject_renamed_icon (const char *icon, const char *substitute)
154 GtkIconTheme *theme = gtk_icon_theme_get_default ();
155 if (!gtk_icon_theme_has_icon (theme, icon)
156 && gtk_icon_theme_has_icon (theme, substitute))
158 gint *sizes = gtk_icon_theme_get_icon_sizes (theme, substitute);
161 for (p = sizes; *p != 0; p++)
166 pb = gtk_icon_theme_load_icon (theme, substitute, size, 0, NULL);
169 GdkPixbuf *copy = gdk_pixbuf_copy (pb);
171 gtk_icon_theme_add_builtin_icon (icon, size, copy);
177 /* Avoid a bug in GTK+ 2.22 that can cause a segfault at startup time. Earlier
178 and later versions of GTK+ do not have the bug. Bug #31511.
180 Based on this patch against Inkscape:
181 https://launchpadlibrarian.net/60175914/copy_renamed_icons.patch */
183 inject_renamed_icons (void)
185 if (gtk_major_version == 2 && gtk_minor_version == 22)
187 inject_renamed_icon ("gtk-file", "document-x-generic");
188 inject_renamed_icon ("gtk-directory", "folder");
195 int resolution; /* The dimension of the images which will be used */
196 size_t n_sizes; /* The number of items in the array below.
197 This may be zero, in which case the iconset will be wildcarded
198 (used by default when no non-wildcarded set is available) */
199 const GtkIconSize *usage; /* An array determining for what the icon set is used */
202 static const GtkIconSize menus[] = {GTK_ICON_SIZE_MENU};
203 static const GtkIconSize toolbar[] = {GTK_ICON_SIZE_LARGE_TOOLBAR};
206 /* We currently have three icon sets viz: 16x16, 24x24 and 32x32
207 We use the 16x16 for menus, the 32x32 for the toolbar and
208 the 24x24 for everything else.
210 Exactly one element of the following array should have its 2nd and 3rd
213 static const struct icon_size sizemap[] =
215 {16, sizeof (menus) / sizeof (GtkIconSize), menus},
217 {32, sizeof (toolbar) / sizeof (GtkIconSize), toolbar}
222 create_icon_factory (void)
225 GtkIconFactory *factory = gtk_icon_factory_new ();
226 struct icon_context ctx[2];
227 ctx[0] = action_icon_context;
228 ctx[1] = category_icon_context;
229 for (c = 0 ; c < 2 ; ++c)
231 const struct icon_context *ic = &ctx[c];
233 for (i = 0 ; i < ic->n_icons ; ++i)
235 GtkIconSet *icon_set = gtk_icon_set_new ();
237 for (r = 0 ; r < sizeof (sizemap) / sizeof (sizemap[0]); ++r)
240 GtkIconSource *source = gtk_icon_source_new ();
241 gchar *filename = g_strdup_printf ("%s/%s/%dx%d/%s.png", PKGDATADIR,
243 sizemap[r].resolution, sizemap[r].resolution,
245 const char *relocated_filename = relocate (filename);
247 gtk_icon_source_set_filename (source, relocated_filename);
248 gtk_icon_source_set_size_wildcarded (source, sizemap[r].n_sizes <= 0);
249 for (s = 0 ; s < sizemap[r].n_sizes ; ++s)
250 gtk_icon_source_set_size (source, sizemap[r].usage[s]);
251 if (filename != relocated_filename)
252 free (CONST_CAST (char *, relocated_filename));
254 gtk_icon_set_add_source (icon_set, source);
257 gtk_icon_factory_add (factory, ic->icon_name[i], icon_set);
268 /* We have our own icons for some things.
269 But we want the Stock Item to be identical to the Gtk standard
270 ones in all other respects.
272 const struct iconmap map[] = {
273 {GTK_STOCK_NEW, "file-new-document"},
274 {GTK_STOCK_QUIT, "file-quit"},
275 {GTK_STOCK_SAVE, "file-save-document"},
276 {GTK_STOCK_CUT, "edit-cut"},
277 {GTK_STOCK_COPY, "edit-copy"},
278 {GTK_STOCK_PASTE, "edit-paste"},
279 {GTK_STOCK_UNDO, "edit-undo"},
280 {GTK_STOCK_REDO, "edit-redo"},
281 {GTK_STOCK_DELETE, "edit-delete"},
282 {GTK_STOCK_ABOUT, "help-about"},
283 {GTK_STOCK_PRINT, "file-print-document"}
286 GtkStockItem customised[sizeof (map) / sizeof (map[0])];
289 for (i = 0; i < sizeof (map) / sizeof (map[0]); ++i)
291 gtk_stock_lookup (map[i].gtk_id, &customised[i]);
292 customised[i].stock_id = map[i].pspp_id;
297 gtk_stock_add (customised, sizeof (map) / sizeof (map[0]));
301 /* Create our own "pspp-stock-reset" item, using the
302 GTK_STOCK_REFRESH icon set */
303 GtkStockItem items[2] = {
304 {"pspp-stock-reset", N_("_Reset"), 0, 0, PACKAGE},
305 {"pspp-stock-select", N_("_Select"), 0, 0, PACKAGE}
308 gtk_stock_add (items, 2);
310 gtk_icon_factory_add (factory, "pspp-stock-reset",
311 gtk_icon_factory_lookup_default (GTK_STOCK_REFRESH)
314 gtk_icon_factory_add (factory, "pspp-stock-select",
315 gtk_icon_factory_lookup_default (GTK_STOCK_INDEX)
319 gtk_icon_factory_add_default (factory);
323 Convert a filename from the local encoding into "filename" encoding.
324 The return value will be allocated on the heap. It is the responsibility
325 of the caller to free it.
328 local_to_filename_encoding (const char *fn)
330 gchar *filename = NULL;
332 const gchar *local_encoding = NULL;
334 const gboolean local_is_utf8 = g_get_charset (&local_encoding);
336 /* There seems to be no Glib function to convert from local encoding
337 to filename encoding. Therefore it has to be done in two steps:
338 the intermediate encoding is UTF8.
340 Either step could fail. However, in many cases the file can still
341 be loaded even if the conversion fails. So in those cases, after showing
342 a warning, we simply copy the locally encoded filename to the destination
343 and hope for the best.
353 utf8 = g_locale_to_utf8 (fn, -1, NULL, &written, &err);
356 g_warning ("Cannot convert filename from local encoding `%s' to UTF-8: %s",
359 g_clear_error (&err);
366 filename = g_filename_from_utf8 (utf8, written, NULL, NULL, &err);
367 if ( NULL == filename)
369 g_warning ("Cannot convert filename from UTF8 to filename encoding: %s",
371 g_clear_error (&err);
377 if ( filename == NULL)
378 filename = xstrdup (fn);
384 handle_msg (const struct msg *m_, void *lexer_)
386 struct lexer *lexer = lexer_;
389 if (lexer != NULL && m.file_name == NULL)
391 m.file_name = CONST_CAST (char *, lex_get_file_name (lexer));
392 m.first_line = lex_get_first_line_number (lexer, 0);
393 m.last_line = lex_get_last_line_number (lexer, 0);
394 m.first_column = lex_get_first_column (lexer, 0);
395 m.last_column = lex_get_last_column (lexer, 0);
398 message_item_submit (message_item_create (&m));
402 psppire_set_lexer (struct lexer *lexer)
404 msg_set_handler (handle_msg, lexer);