]> git.donarmstrong.com Git - xournal.git/blob - src/main.c
Add internationalization support.
[xournal.git] / src / main.c
1 #ifdef HAVE_CONFIG_H
2 #  include <config.h>
3 #endif
4
5 #include <sys/stat.h>
6 #include <string.h>
7 #include <gtk/gtk.h>
8 #include <libgnomecanvas/libgnomecanvas.h>
9
10 #include "xournal.h"
11 #include "xo-interface.h"
12 #include "xo-support.h"
13 #include "xo-callbacks.h"
14 #include "xo-misc.h"
15 #include "xo-file.h"
16 #include "xo-paint.h"
17 #include "xo-shapes.h"
18
19 GtkWidget *winMain;
20 GnomeCanvas *canvas;
21
22 struct Journal journal; // the journal
23 struct BgPdf bgpdf;  // the PDF loader stuff
24 struct UIData ui;   // the user interface data
25 struct UndoItem *undo, *redo; // the undo and redo stacks
26
27 double DEFAULT_ZOOM;
28
29 // prevent interface items from getting bogus XInput events
30 gboolean filter_extended_events (GtkWidget *widget, GdkEvent *event,
31                                    gpointer user_data)
32 {
33   // prevent scrollbars from reacting to XInput events
34   if (event->type == GDK_MOTION_NOTIFY &&
35       event->motion.device != gdk_device_get_core_pointer())
36     return TRUE;
37   if ((event->type == GDK_BUTTON_PRESS || event->type == GDK_2BUTTON_PRESS ||
38       event->type == GDK_3BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) &&
39       event->button.device != gdk_device_get_core_pointer())
40     return TRUE;
41   return FALSE;
42 }
43
44 void init_stuff (int argc, char *argv[])
45 {
46   GtkWidget *w;
47   GList *dev_list;
48   GdkDevice *device;
49   GdkScreen *screen;
50   int i, j;
51   struct Brush *b;
52   gboolean can_xinput, success;
53   gchar *tmppath, *tmpfn;
54
55   // create some data structures needed to populate the preferences
56   ui.default_page.bg = g_new(struct Background, 1);
57
58   // initialize config file names
59   tmppath = g_build_filename(g_get_home_dir(), CONFIG_DIR, NULL);
60   mkdir(tmppath, 0700); // safer (MRU data may be confidential)
61   ui.mrufile = g_build_filename(tmppath, MRU_FILE, NULL);
62   ui.configfile = g_build_filename(tmppath, CONFIG_FILE, NULL);
63   g_free(tmppath);
64
65   // initialize preferences
66   init_config_default();
67   load_config_from_file();
68   ui.font_name = g_strdup(ui.default_font_name);
69   ui.font_size = ui.default_font_size;
70   ui.hiliter_alpha_mask = 0xffffff00 + (guint)(255*ui.hiliter_opacity);
71
72   // we need an empty canvas prior to creating the journal structures
73   canvas = GNOME_CANVAS (gnome_canvas_new_aa ());
74
75   // initialize data
76   ui.default_page.bg->canvas_item = NULL;
77   ui.layerbox_length = 0;
78
79   if (argc > 2 || (argc == 2 && argv[1][0] == '-')) {
80     printf(_("Invalid command line parameters.\n"
81            "Usage: %s [filename.xoj]\n"), argv[0]);
82     gtk_exit(0);
83   }
84    
85   undo = NULL; redo = NULL;
86   journal.pages = NULL;
87   bgpdf.status = STATUS_NOT_INIT;
88
89   new_journal();  
90   
91   ui.cur_item_type = ITEM_NONE;
92   ui.cur_item = NULL;
93   ui.cur_path.coords = NULL;
94   ui.cur_path_storage_alloc = 0;
95   ui.cur_path.ref_count = 1;
96   ui.cur_widths = NULL;
97   ui.cur_widths_storage_alloc = 0;
98
99   ui.selection = NULL;
100   ui.cursor = NULL;
101
102   ui.cur_brush = &(ui.brushes[0][ui.toolno[0]]);
103   for (j=0; j<=NUM_BUTTONS; j++)
104     for (i=0; i < NUM_STROKE_TOOLS; i++) {
105       b = &(ui.brushes[j][i]);
106       b->tool_type = i;
107       b->color_rgba = predef_colors_rgba[b->color_no];
108       if (i == TOOL_HIGHLIGHTER) {
109         b->color_rgba &= ui.hiliter_alpha_mask;
110       }
111       b->thickness = predef_thickness[i][b->thickness_no];
112     }
113   for (i=0; i<NUM_STROKE_TOOLS; i++)
114     g_memmove(ui.default_brushes+i, &(ui.brushes[0][i]), sizeof(struct Brush));
115
116   ui.cur_mapping = 0;
117   
118   reset_recognizer();
119
120   // initialize various interface elements
121   
122   gtk_window_set_default_size(GTK_WINDOW (winMain), ui.window_default_width, ui.window_default_height);
123   if (ui.maximize_at_start) gtk_window_maximize(GTK_WINDOW (winMain));
124   update_toolbar_and_menu();
125   update_font_button();
126
127   gtk_check_menu_item_set_active(
128     GTK_CHECK_MENU_ITEM(GET_COMPONENT("journalApplyAllPages")), ui.bg_apply_all_pages);
129   if (ui.fullscreen) {
130     gtk_check_menu_item_set_active(
131       GTK_CHECK_MENU_ITEM(GET_COMPONENT("viewFullscreen")), TRUE);
132     gtk_toggle_tool_button_set_active(
133       GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonFullscreen")), TRUE);
134     gtk_window_fullscreen(GTK_WINDOW(winMain));
135   }
136
137   allow_all_accels();
138   add_scroll_bindings();
139
140   // set up and initialize the canvas
141
142   gtk_widget_show (GTK_WIDGET (canvas));
143   w = GET_COMPONENT("scrolledwindowMain");
144   gtk_container_add (GTK_CONTAINER (w), GTK_WIDGET (canvas));
145   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (w), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
146   gtk_widget_set_events (GTK_WIDGET (canvas), GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
147   gnome_canvas_set_pixels_per_unit (canvas, ui.zoom);
148   gnome_canvas_set_center_scroll_region (canvas, TRUE);
149   gtk_layout_get_hadjustment(GTK_LAYOUT (canvas))->step_increment = ui.scrollbar_step_increment;
150   gtk_layout_get_vadjustment(GTK_LAYOUT (canvas))->step_increment = ui.scrollbar_step_increment;
151
152   // set up the page size and canvas size
153   update_page_stuff();
154
155   g_signal_connect ((gpointer) canvas, "button_press_event",
156                     G_CALLBACK (on_canvas_button_press_event),
157                     NULL);
158   g_signal_connect ((gpointer) canvas, "button_release_event",
159                     G_CALLBACK (on_canvas_button_release_event),
160                     NULL);
161   g_signal_connect ((gpointer) canvas, "enter_notify_event",
162                     G_CALLBACK (on_canvas_enter_notify_event),
163                     NULL);
164   g_signal_connect ((gpointer) canvas, "expose_event",
165                     G_CALLBACK (on_canvas_expose_event),
166                     NULL);
167   g_signal_connect ((gpointer) canvas, "key_press_event",
168                     G_CALLBACK (on_canvas_key_press_event),
169                     NULL);
170   g_signal_connect ((gpointer) canvas, "motion_notify_event",
171                     G_CALLBACK (on_canvas_motion_notify_event),
172                     NULL);
173   g_signal_connect ((gpointer) gtk_layout_get_vadjustment(GTK_LAYOUT(canvas)),
174                     "value-changed", G_CALLBACK (on_vscroll_changed),
175                     NULL);
176   g_object_set_data (G_OBJECT (winMain), "canvas", canvas);
177
178   screen = gtk_widget_get_screen(winMain);
179   ui.screen_width = gdk_screen_get_width(screen);
180   ui.screen_height = gdk_screen_get_height(screen);
181   
182   can_xinput = FALSE;
183   dev_list = gdk_devices_list();
184   while (dev_list != NULL) {
185     device = (GdkDevice *)dev_list->data;
186     if (device != gdk_device_get_core_pointer()) {
187       /* get around a GDK bug: map the valuator range CORRECTLY to [0,1] */
188 #ifdef ENABLE_XINPUT_BUGFIX
189       gdk_device_set_axis_use(device, 0, GDK_AXIS_IGNORE);
190       gdk_device_set_axis_use(device, 1, GDK_AXIS_IGNORE);
191 #endif
192       gdk_device_set_mode(device, GDK_MODE_SCREEN);
193       if (g_str_has_suffix(device->name, "eraser"))
194         gdk_device_set_source(device, GDK_SOURCE_ERASER);
195       can_xinput = TRUE;
196     }
197     dev_list = dev_list->next;
198   }
199   if (!can_xinput)
200     gtk_widget_set_sensitive(GET_COMPONENT("optionsUseXInput"), FALSE);
201
202   ui.use_xinput = ui.allow_xinput && can_xinput;
203
204   gtk_check_menu_item_set_active(
205     GTK_CHECK_MENU_ITEM(GET_COMPONENT("optionsAntialiasBG")), ui.antialias_bg);
206   gtk_check_menu_item_set_active(
207     GTK_CHECK_MENU_ITEM(GET_COMPONENT("optionsProgressiveBG")), ui.progressive_bg);
208   gtk_check_menu_item_set_active(
209     GTK_CHECK_MENU_ITEM(GET_COMPONENT("optionsPrintRuling")), ui.print_ruling);
210   gtk_check_menu_item_set_active(
211     GTK_CHECK_MENU_ITEM(GET_COMPONENT("optionsLeftHanded")), ui.left_handed);
212   gtk_check_menu_item_set_active(
213     GTK_CHECK_MENU_ITEM(GET_COMPONENT("optionsShortenMenus")), ui.shorten_menus);
214   gtk_check_menu_item_set_active(
215     GTK_CHECK_MENU_ITEM(GET_COMPONENT("optionsAutoSavePrefs")), ui.auto_save_prefs);
216   
217   hide_unimplemented();
218
219   update_undo_redo_enabled();
220   update_copy_paste_enabled();
221   update_vbox_order(ui.vertical_order[ui.fullscreen?1:0]);
222   gtk_widget_grab_focus(GTK_WIDGET(canvas));
223
224   // show everything...
225   
226   gtk_widget_show (winMain);
227   update_cursor();
228   
229   /* this will cause extension events to get enabled/disabled, but
230      we need the windows to be mapped first */
231   gtk_check_menu_item_set_active(
232     GTK_CHECK_MENU_ITEM(GET_COMPONENT("optionsUseXInput")), ui.use_xinput);
233
234   /* fix a bug in GTK+ 2.16 and beyond: scrollbars shouldn't get extended
235      input events from pointer motion when cursor moves into main window */
236 #if GTK_CHECK_VERSION(2,14,0)
237   if (!gtk_check_version(2, 14, 0)) {
238     g_signal_connect (
239       GET_COMPONENT("menubar"),
240       "event", G_CALLBACK (filter_extended_events),
241       NULL);
242     g_signal_connect (
243       GET_COMPONENT("toolbarMain"),
244       "event", G_CALLBACK (filter_extended_events),
245       NULL);
246     g_signal_connect (
247       GET_COMPONENT("toolbarPen"),
248       "event", G_CALLBACK (filter_extended_events),
249       NULL);
250     g_signal_connect (
251       GET_COMPONENT("statusbar"),
252       "event", G_CALLBACK (filter_extended_events),
253       NULL);
254     g_signal_connect (
255       (gpointer)(gtk_scrolled_window_get_vscrollbar(GTK_SCROLLED_WINDOW(w))),
256       "event", G_CALLBACK (filter_extended_events),
257       NULL);
258     g_signal_connect (
259       (gpointer)(gtk_scrolled_window_get_hscrollbar(GTK_SCROLLED_WINDOW(w))),
260       "event", G_CALLBACK (filter_extended_events),
261       NULL);
262   }
263 #endif
264
265   // load the MRU
266   
267   init_mru();
268   
269   // and finally, open a file specified on the command line
270   // (moved here because display parameters weren't initialized yet...)
271   
272   if (argc == 1) return;
273   set_cursor_busy(TRUE);
274   if (g_path_is_absolute(argv[1]))
275     tmpfn = g_strdup(argv[1]);
276   else {
277     tmppath = g_get_current_dir();
278     tmpfn = g_build_filename(tmppath, argv[1], NULL);
279     g_free(tmppath);
280   }
281   success = open_journal(tmpfn);
282   g_free(tmpfn);
283   set_cursor_busy(FALSE);
284   if (!success) {
285     w = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
286        GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening file '%s'"), argv[1]);
287     gtk_dialog_run(GTK_DIALOG(w));
288     gtk_widget_destroy(w);
289   }
290 }
291
292
293 int
294 main (int argc, char *argv[])
295 {
296   gchar *path, *path1, *path2;
297   
298 #ifdef ENABLE_NLS
299   bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
300   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
301   textdomain (GETTEXT_PACKAGE);
302 #endif
303   
304   gtk_set_locale ();
305   gtk_init (&argc, &argv);
306
307   add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
308   path = g_path_get_dirname(argv[0]);
309   path1 = g_build_filename(path, "pixmaps", NULL);
310   path2 = g_build_filename(path, "..", "pixmaps", NULL);
311   add_pixmap_directory (path1);
312   add_pixmap_directory (path2);
313   add_pixmap_directory (path);
314   g_free(path);
315   g_free(path1);
316   g_free(path2);
317
318   /*
319    * The following code was added by Glade to create one of each component
320    * (except popup menus), just so that you see something after building
321    * the project. Delete any components that you don't want shown initially.
322    */
323   winMain = create_winMain ();
324   
325   init_stuff (argc, argv);
326   gtk_window_set_icon(GTK_WINDOW(winMain), create_pixbuf("xournal.png"));
327   
328   gtk_main ();
329   
330   if (bgpdf.status != STATUS_NOT_INIT) shutdown_bgpdf();
331
332   save_mru_list();
333   if (ui.auto_save_prefs) save_config_to_file();
334   
335   return 0;
336 }
337