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 enum detect_result res = any_reader_may_open (filename);
110 /* Check to see if the file is a .sav or a .por file. If not
111 assume that it is a syntax file */
113 open_data_window (NULL, filename, NULL);
114 else if (res == ANY_NO)
116 create_data_window ();
117 open_syntax_window (filename, NULL);
123 create_data_window ();
136 func (gpointer key, gpointer value, gpointer data)
139 PsppireWindow *window = PSPPIRE_WINDOW (value);
141 g_signal_emit_by_name (window, "delete-event", 0, &rv);
147 PsppireWindowRegister *reg = psppire_window_register_new ();
148 psppire_window_register_foreach (reg, func, NULL);
154 inject_renamed_icon (const char *icon, const char *substitute)
156 GtkIconTheme *theme = gtk_icon_theme_get_default ();
157 if (!gtk_icon_theme_has_icon (theme, icon)
158 && gtk_icon_theme_has_icon (theme, substitute))
160 gint *sizes = gtk_icon_theme_get_icon_sizes (theme, substitute);
163 for (p = sizes; *p != 0; p++)
168 pb = gtk_icon_theme_load_icon (theme, substitute, size, 0, NULL);
171 GdkPixbuf *copy = gdk_pixbuf_copy (pb);
173 gtk_icon_theme_add_builtin_icon (icon, size, copy);
179 /* Avoid a bug in GTK+ 2.22 that can cause a segfault at startup time. Earlier
180 and later versions of GTK+ do not have the bug. Bug #31511.
182 Based on this patch against Inkscape:
183 https://launchpadlibrarian.net/60175914/copy_renamed_icons.patch */
185 inject_renamed_icons (void)
187 if (gtk_major_version == 2 && gtk_minor_version == 22)
189 inject_renamed_icon ("gtk-file", "document-x-generic");
190 inject_renamed_icon ("gtk-directory", "folder");
197 int resolution; /* The dimension of the images which will be used */
198 size_t n_sizes; /* The number of items in the array below.
199 This may be zero, in which case the iconset will be wildcarded
200 (used by default when no non-wildcarded set is available) */
201 const GtkIconSize *usage; /* An array determining for what the icon set is used */
204 static const GtkIconSize menus[] = {GTK_ICON_SIZE_MENU};
205 static const GtkIconSize toolbar[] = {GTK_ICON_SIZE_LARGE_TOOLBAR};
208 /* We currently have three icon sets viz: 16x16, 24x24 and 32x32
209 We use the 16x16 for menus, the 32x32 for the toolbar and
210 the 24x24 for everything else.
212 Exactly one element of the following array should have its 2nd and 3rd
215 static const struct icon_size sizemap[] =
217 {16, sizeof (menus) / sizeof (GtkIconSize), menus},
219 {32, sizeof (toolbar) / sizeof (GtkIconSize), toolbar}
224 create_icon_factory (void)
227 GtkIconFactory *factory = gtk_icon_factory_new ();
228 struct icon_context ctx[2];
229 ctx[0] = action_icon_context;
230 ctx[1] = category_icon_context;
231 for (c = 0 ; c < 2 ; ++c)
233 const struct icon_context *ic = &ctx[c];
235 for (i = 0 ; i < ic->n_icons ; ++i)
237 GtkIconSet *icon_set = gtk_icon_set_new ();
239 for (r = 0 ; r < sizeof (sizemap) / sizeof (sizemap[0]); ++r)
242 GtkIconSource *source = gtk_icon_source_new ();
243 gchar *filename = g_strdup_printf ("%s/%s/%dx%d/%s.png", PKGDATADIR,
245 sizemap[r].resolution, sizemap[r].resolution,
247 const char *relocated_filename = relocate (filename);
249 gtk_icon_source_set_filename (source, relocated_filename);
250 gtk_icon_source_set_size_wildcarded (source, sizemap[r].n_sizes <= 0);
251 for (s = 0 ; s < sizemap[r].n_sizes ; ++s)
252 gtk_icon_source_set_size (source, sizemap[r].usage[s]);
253 if (filename != relocated_filename)
254 free (CONST_CAST (char *, relocated_filename));
256 gtk_icon_set_add_source (icon_set, source);
259 gtk_icon_factory_add (factory, ic->icon_name[i], icon_set);
270 /* We have our own icons for some things.
271 But we want the Stock Item to be identical to the Gtk standard
272 ones in all other respects.
274 const struct iconmap map[] = {
275 {GTK_STOCK_NEW, "file-new-document"},
276 {GTK_STOCK_QUIT, "file-quit"},
277 {GTK_STOCK_SAVE, "file-save-document"},
278 {GTK_STOCK_CUT, "edit-cut"},
279 {GTK_STOCK_COPY, "edit-copy"},
280 {GTK_STOCK_PASTE, "edit-paste"},
281 {GTK_STOCK_UNDO, "edit-undo"},
282 {GTK_STOCK_REDO, "edit-redo"},
283 {GTK_STOCK_DELETE, "edit-delete"},
284 {GTK_STOCK_ABOUT, "help-about"},
285 {GTK_STOCK_PRINT, "file-print-document"}
288 GtkStockItem customised[sizeof (map) / sizeof (map[0])];
291 for (i = 0; i < sizeof (map) / sizeof (map[0]); ++i)
293 gtk_stock_lookup (map[i].gtk_id, &customised[i]);
294 customised[i].stock_id = map[i].pspp_id;
299 gtk_stock_add (customised, sizeof (map) / sizeof (map[0]));
303 /* Create our own "pspp-stock-reset" item, using the
304 GTK_STOCK_REFRESH icon set */
305 GtkStockItem items[2] = {
306 {"pspp-stock-reset", N_("_Reset"), 0, 0, PACKAGE},
307 {"pspp-stock-select", N_("_Select"), 0, 0, PACKAGE}
310 gtk_stock_add (items, 2);
312 gtk_icon_factory_add (factory, "pspp-stock-reset",
313 gtk_icon_factory_lookup_default (GTK_STOCK_REFRESH)
316 gtk_icon_factory_add (factory, "pspp-stock-select",
317 gtk_icon_factory_lookup_default (GTK_STOCK_INDEX)
321 gtk_icon_factory_add_default (factory);
325 Convert a filename from the local encoding into "filename" encoding.
326 The return value will be allocated on the heap. It is the responsibility
327 of the caller to free it.
330 local_to_filename_encoding (const char *fn)
332 gchar *filename = NULL;
334 const gchar *local_encoding = NULL;
336 const gboolean local_is_utf8 = g_get_charset (&local_encoding);
338 /* There seems to be no Glib function to convert from local encoding
339 to filename encoding. Therefore it has to be done in two steps:
340 the intermediate encoding is UTF8.
342 Either step could fail. However, in many cases the file can still
343 be loaded even if the conversion fails. So in those cases, after showing
344 a warning, we simply copy the locally encoded filename to the destination
345 and hope for the best.
355 utf8 = g_locale_to_utf8 (fn, -1, NULL, &written, &err);
358 g_warning ("Cannot convert filename from local encoding `%s' to UTF-8: %s",
361 g_clear_error (&err);
368 filename = g_filename_from_utf8 (utf8, written, NULL, NULL, &err);
369 if ( NULL == filename)
371 g_warning ("Cannot convert filename from UTF8 to filename encoding: %s",
373 g_clear_error (&err);
379 if ( filename == NULL)
380 filename = xstrdup (fn);
386 handle_msg (const struct msg *m_, void *lexer_)
388 struct lexer *lexer = lexer_;
391 if (lexer != NULL && m.file_name == NULL)
393 m.file_name = CONST_CAST (char *, lex_get_file_name (lexer));
394 m.first_line = lex_get_first_line_number (lexer, 0);
395 m.last_line = lex_get_last_line_number (lexer, 0);
396 m.first_column = lex_get_first_column (lexer, 0);
397 m.last_column = lex_get_last_column (lexer, 0);
400 message_item_submit (message_item_create (&m));
404 psppire_set_lexer (struct lexer *lexer)
406 msg_set_handler (handle_msg, lexer);