]> git.donarmstrong.com Git - xournal.git/blob - src/xo-callbacks.c
3b2b3199421c8e5c5c034d0b1721ef69081735cc
[xournal.git] / src / xo-callbacks.c
1 /*
2  *  This program is free software; you can redistribute it and/or
3  *  modify it under the terms of the GNU General Public
4  *  License as published by the Free Software Foundation; either
5  *  version 2 of the License, or (at your option) any later version.
6  *
7  *  This software is distributed in the hope that it will be useful,
8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of  
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10  *  General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
14  */
15
16
17 #ifdef HAVE_CONFIG_H
18 #  include <config.h>
19 #endif
20
21 #include <math.h>
22 #include <string.h>
23 #include <gtk/gtk.h>
24 #include <libgnomecanvas/libgnomecanvas.h>
25 #include <time.h>
26 #include <glib/gstdio.h>
27 #include <gdk/gdkkeysyms.h>
28
29 #include "xournal.h"
30 #include "xo-callbacks.h"
31 #include "xo-interface.h"
32 #include "xo-support.h"
33 #include "xo-misc.h"
34 #include "xo-file.h"
35 #include "xo-paint.h"
36 #include "xo-print.h"
37 #include "xo-shapes.h"
38
39 void
40 on_fileNew_activate                    (GtkMenuItem     *menuitem,
41                                         gpointer         user_data)
42 {
43   end_text();
44   if (close_journal()) {
45     new_journal();
46     ui.zoom = ui.startup_zoom;
47     update_page_stuff();
48     gtk_adjustment_set_value(gtk_layout_get_vadjustment(GTK_LAYOUT(canvas)), 0);
49     gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
50   }
51 }
52
53
54 void
55 on_fileNewBackground_activate          (GtkMenuItem     *menuitem,
56                                         gpointer         user_data)
57 {
58   GtkWidget *dialog, *attach_opt;
59   GtkFileFilter *filt_all, *filt_pdf;
60   char *filename;
61   int file_domain;
62   gboolean success;
63   
64   end_text();
65   if (!ok_to_close()) return; // user aborted on save confirmation
66   
67   dialog = gtk_file_chooser_dialog_new(_("Open PDF"), GTK_WINDOW (winMain),
68      GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
69      GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
70 #ifdef FILE_DIALOG_SIZE_BUGFIX
71   gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
72 #endif
73      
74   filt_all = gtk_file_filter_new();
75   gtk_file_filter_set_name(filt_all, _("All files"));
76   gtk_file_filter_add_pattern(filt_all, "*");
77   filt_pdf = gtk_file_filter_new();
78   gtk_file_filter_set_name(filt_pdf, _("PDF files"));
79   gtk_file_filter_add_pattern(filt_pdf, "*.pdf");
80   gtk_file_filter_add_pattern(filt_pdf, "*.PDF");
81   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pdf);
82   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
83
84   if (ui.default_path!=NULL) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
85
86   attach_opt = gtk_check_button_new_with_label(_("Attach file to the journal"));
87   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(attach_opt), FALSE);
88   gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER (dialog), attach_opt);
89   
90   if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
91     gtk_widget_destroy(dialog);
92     return;
93   }
94   filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
95   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(attach_opt)))
96        file_domain = DOMAIN_ATTACH;
97   else file_domain = DOMAIN_ABSOLUTE;
98   
99   gtk_widget_destroy(dialog);
100
101   set_cursor_busy(TRUE);
102   ui.saved = TRUE; // force close_journal to work
103   close_journal();
104   while (bgpdf.status != STATUS_NOT_INIT) {
105     // waiting for pdf processes to finish dying
106     gtk_main_iteration(); 
107   }
108   new_journal();
109   ui.zoom = ui.startup_zoom;
110   gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
111   update_page_stuff();
112   success = init_bgpdf(filename, TRUE, file_domain);
113   set_cursor_busy(FALSE);
114   if (success) {
115     g_free(filename);
116     return;
117   }
118   
119   /* open failed */
120   dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
121     GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening file '%s'"), filename);
122   gtk_dialog_run(GTK_DIALOG(dialog));
123   gtk_widget_destroy(dialog);
124   g_free(filename);
125 }
126
127
128 void
129 on_fileOpen_activate                   (GtkMenuItem     *menuitem,
130                                         gpointer         user_data)
131 {
132   GtkWidget *dialog;
133   GtkFileFilter *filt_all, *filt_xoj;
134   char *filename;
135   gboolean success;
136   
137   end_text();
138   if (!ok_to_close()) return; // user aborted on save confirmation
139   
140   dialog = gtk_file_chooser_dialog_new(_("Open Journal"), GTK_WINDOW (winMain),
141      GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
142      GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
143 #ifdef FILE_DIALOG_SIZE_BUGFIX
144   gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
145 #endif
146      
147   filt_all = gtk_file_filter_new();
148   gtk_file_filter_set_name(filt_all, _("All files"));
149   gtk_file_filter_add_pattern(filt_all, "*");
150   filt_xoj = gtk_file_filter_new();
151   gtk_file_filter_set_name(filt_xoj, _("Xournal files"));
152   gtk_file_filter_add_pattern(filt_xoj, "*.xoj");
153   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_xoj);
154   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
155
156   if (ui.default_path!=NULL) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
157
158   if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
159     gtk_widget_destroy(dialog);
160     return;
161   }
162   filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
163   gtk_widget_destroy(dialog);
164
165   set_cursor_busy(TRUE);
166   success = open_journal(filename);
167   set_cursor_busy(FALSE);
168   if (success) { g_free(filename); return; }
169   
170   /* open failed */
171   dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
172     GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening file '%s'"), filename);
173   gtk_dialog_run(GTK_DIALOG(dialog));
174   gtk_widget_destroy(dialog);
175   g_free(filename);
176
177 }
178
179
180 void
181 on_fileSave_activate                   (GtkMenuItem     *menuitem,
182                                         gpointer         user_data)
183 {
184   GtkWidget *dialog;
185   
186   end_text();
187   if (ui.filename == NULL) {
188     on_fileSaveAs_activate(menuitem, user_data);
189     return;
190   }
191   set_cursor_busy(TRUE);
192   if (save_journal(ui.filename)) { // success
193     set_cursor_busy(FALSE);
194     ui.saved = TRUE;
195     return;
196   }
197   set_cursor_busy(FALSE);
198   /* save failed */
199   dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
200     GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error saving file '%s'"), ui.filename);
201   gtk_dialog_run(GTK_DIALOG(dialog));
202   gtk_widget_destroy(dialog);
203 }
204
205
206 void
207 on_fileSaveAs_activate                 (GtkMenuItem     *menuitem,
208                                         gpointer         user_data)
209 {
210   GtkWidget *dialog, *warning_dialog;
211   GtkFileFilter *filt_all, *filt_xoj;
212   char *filename;
213   char stime[30];
214   time_t curtime;
215   gboolean warn;
216   struct stat stat_buf;
217   
218   end_text();
219   dialog = gtk_file_chooser_dialog_new(_("Save Journal"), GTK_WINDOW (winMain),
220      GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
221      GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
222 #ifdef FILE_DIALOG_SIZE_BUGFIX
223   gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
224 #endif
225      
226   if (ui.filename!=NULL) {
227     gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), ui.filename);
228     gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), g_basename(ui.filename));
229   } 
230   else
231   if (bgpdf.status!=STATUS_NOT_INIT && bgpdf.file_domain == DOMAIN_ABSOLUTE 
232       && bgpdf.filename != NULL) {
233     filename = g_strdup_printf("%s.xoj", bgpdf.filename->s);
234     gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), filename);
235     gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), g_basename(filename));
236     g_free(filename); 
237   }
238   else {
239     curtime = time(NULL);
240     strftime(stime, 30, "%Y-%m-%d-Note-%H-%M.xoj", localtime(&curtime));
241     if (ui.default_path!=NULL)
242       gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
243     gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), stime);
244   }
245      
246   filt_all = gtk_file_filter_new();
247   gtk_file_filter_set_name(filt_all, _("All files"));
248   gtk_file_filter_add_pattern(filt_all, "*");
249   filt_xoj = gtk_file_filter_new();
250   gtk_file_filter_set_name(filt_xoj, _("Xournal files"));
251   gtk_file_filter_add_pattern(filt_xoj, "*.xoj");
252   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_xoj);
253   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
254   
255   // somehow this doesn't seem to be set by default
256   gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
257
258   do {
259     if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
260       gtk_widget_destroy(dialog);
261       return;
262     }
263     filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
264     warn = g_file_test (filename, G_FILE_TEST_EXISTS);
265     if (warn) { // ok to overwrite an empty file
266       if (!g_stat(filename, &stat_buf))
267         if (stat_buf.st_size == 0) warn=FALSE;
268     }
269     if (warn && ui.filename!=NULL) { // ok to overwrite oneself
270       if (ui.filename[0]=='/' && !strcmp(ui.filename, filename)) warn=FALSE;
271       if (ui.filename[0]!='/' && g_str_has_suffix(filename, ui.filename)) warn=FALSE;
272     }
273     if (warn) {
274       warning_dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), 
275         GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
276         _("Should the file %s be overwritten?"), filename);
277       if (gtk_dialog_run(GTK_DIALOG(warning_dialog)) == GTK_RESPONSE_YES)
278         warn = FALSE;
279       gtk_widget_destroy(warning_dialog);
280     }
281   } while (warn);
282
283   gtk_widget_destroy(dialog);
284
285   set_cursor_busy(TRUE);
286   if (save_journal(filename)) { // success
287     ui.saved = TRUE;
288     set_cursor_busy(FALSE);
289     update_file_name(filename);
290     return;
291   }
292   set_cursor_busy(FALSE);
293   /* save failed */
294   dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
295     GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error saving file '%s'"), filename);
296   gtk_dialog_run(GTK_DIALOG(dialog));
297   gtk_widget_destroy(dialog);
298   g_free(filename);
299 }
300
301
302 void
303 on_filePrintOptions_activate           (GtkMenuItem     *menuitem,
304                                         gpointer         user_data)
305 {
306
307 }
308
309 void
310 on_filePrint_activate                  (GtkMenuItem     *menuitem,
311                                         gpointer         user_data)
312 {
313 #if GTK_CHECK_VERSION(2, 10, 0)
314   GtkPrintOperation *print;
315   GtkPrintOperationResult res;
316   
317   int fromPage, toPage;
318   int response;
319   char *in_fn, *p;
320
321   end_text();
322   if (!gtk_check_version(2, 10, 0)) {
323     print = gtk_print_operation_new();
324 /*
325     if (!ui.print_settings)
326       ui.print_settings = gtk_print_settings_new();
327     if (ui.filename!=NULL) {
328       if (g_str_has_suffix(ui.filename, ".xoj")) {
329         in_fn = g_strdup(ui.filename);
330         g_strlcpy(g_strrstr(in_fn, "xoj"), "pdf", 4);
331       } 
332       else in_fn = g_strdup_printf("%s.pdf", ui.filename);
333       gtk_print_settings_set(ui.print_settings, GTK_PRINT_SETTINGS_OUTPUT_URI,
334          g_filename_to_uri(in_fn, NULL, NULL));
335       g_free(in_fn);
336     }
337 */
338     if (ui.print_settings!=NULL)
339        gtk_print_operation_set_print_settings (print, ui.print_settings);
340     gtk_print_operation_set_n_pages(print, journal.npages);
341     gtk_print_operation_set_current_page(print, ui.pageno);
342     gtk_print_operation_set_show_progress(print, TRUE);
343     if (ui.filename!=NULL) {
344       p = g_utf8_strrchr(ui.filename, -1, '/');
345       if (p==NULL) p = ui.filename;
346       else p++;
347       gtk_print_operation_set_job_name(print, p);
348     }
349     g_signal_connect (print, "draw_page", G_CALLBACK (print_job_render_page), NULL);
350     res = gtk_print_operation_run(print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
351                                   GTK_WINDOW(winMain), NULL);
352     if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
353       if (ui.print_settings!=NULL) g_object_unref(ui.print_settings);
354       ui.print_settings = g_object_ref(gtk_print_operation_get_print_settings(print));
355     }
356     g_object_unref(print);
357   }
358 #endif
359 }
360
361
362 void
363 on_filePrintPDF_activate               (GtkMenuItem     *menuitem,
364                                         gpointer         user_data)
365 {
366
367   GtkWidget *dialog, *warning_dialog;
368   GtkFileFilter *filt_all, *filt_pdf;
369   char *filename, *in_fn;
370   char stime[30];
371   time_t curtime;
372   gboolean warn;
373   
374   end_text();
375   dialog = gtk_file_chooser_dialog_new(_("Export to PDF"), GTK_WINDOW (winMain),
376      GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
377      GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
378 #ifdef FILE_DIALOG_SIZE_BUGFIX
379   gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
380 #endif
381      
382   if (ui.filename!=NULL) {
383     if (g_str_has_suffix(ui.filename, ".xoj")) {
384       in_fn = g_strdup(ui.filename);
385       g_strlcpy(g_strrstr(in_fn, "xoj"), "pdf", 4);
386     } 
387     else
388       in_fn = g_strdup_printf("%s.pdf", ui.filename);
389     gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), in_fn);
390     gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), g_basename(in_fn));
391   } else {
392     curtime = time(NULL);
393     strftime(stime, 30, "%Y-%m-%d-Note-%H-%M.pdf", localtime(&curtime));
394     if (ui.default_path!=NULL)
395       gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
396     gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), stime);
397     in_fn = NULL;
398   }
399      
400   filt_all = gtk_file_filter_new();
401   gtk_file_filter_set_name(filt_all, _("All files"));
402   gtk_file_filter_add_pattern(filt_all, "*");
403   filt_pdf = gtk_file_filter_new();
404   gtk_file_filter_set_name(filt_pdf, _("PDF files"));
405   gtk_file_filter_add_pattern(filt_pdf, "*.pdf");
406   gtk_file_filter_add_pattern(filt_pdf, "*.PDF");
407   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pdf);
408   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
409   gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
410   g_free(in_fn);
411   
412   do {
413     if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
414       gtk_widget_destroy(dialog);
415       return;
416     }
417     filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
418     warn = g_file_test(filename, G_FILE_TEST_EXISTS);
419     if (warn) {
420       warning_dialog = gtk_message_dialog_new(GTK_WINDOW(winMain),
421         GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
422         _("Should the file %s be overwritten?"), filename);
423       if (gtk_dialog_run(GTK_DIALOG(warning_dialog)) == GTK_RESPONSE_YES)
424         warn = FALSE;
425       gtk_widget_destroy(warning_dialog);
426     }
427   } while(warn);
428     
429   gtk_widget_destroy(dialog);
430
431   set_cursor_busy(TRUE);
432   if (!print_to_pdf(filename)) {
433     set_cursor_busy(FALSE);
434     dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
435       GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error creating file '%s'"), filename);
436     gtk_dialog_run(GTK_DIALOG(dialog));
437     gtk_widget_destroy(dialog);
438   }
439   set_cursor_busy(FALSE);
440   g_free(filename);
441 }
442
443
444 void
445 on_fileQuit_activate                   (GtkMenuItem     *menuitem,
446                                         gpointer         user_data)
447 {
448   end_text();
449   if (ok_to_close()) gtk_main_quit ();
450 }
451
452
453 void
454 on_editUndo_activate                   (GtkMenuItem     *menuitem,
455                                         gpointer         user_data)
456 {
457   struct UndoItem *u;
458   GList *list, *itemlist;
459   struct UndoErasureData *erasure;
460   struct Item *it;
461   struct Brush tmp_brush;
462   struct Background *tmp_bg;
463   double tmp_x, tmp_y;
464   gchar *tmpstr;
465   GnomeCanvasGroup *group;
466   
467   end_text();
468   if (undo == NULL) return; // nothing to undo!
469   reset_selection(); // safer
470   reset_recognizer(); // safer
471   if (undo->type == ITEM_STROKE || undo->type == ITEM_TEXT) {
472     // we're keeping the stroke info, but deleting the canvas item
473     gtk_object_destroy(GTK_OBJECT(undo->item->canvas_item));
474     undo->item->canvas_item = NULL;
475     // we also remove the object from its layer!
476     undo->layer->items = g_list_remove(undo->layer->items, undo->item);
477     undo->layer->nitems--;
478   }
479   else if (undo->type == ITEM_ERASURE || undo->type == ITEM_RECOGNIZER) {
480     for (list = undo->erasurelist; list!=NULL; list = list->next) {
481       erasure = (struct UndoErasureData *)list->data;
482       // delete all the created items
483       for (itemlist = erasure->replacement_items; itemlist!=NULL; itemlist = itemlist->next) {
484         it = (struct Item *)itemlist->data;
485         gtk_object_destroy(GTK_OBJECT(it->canvas_item));
486         it->canvas_item = NULL;
487         undo->layer->items = g_list_remove(undo->layer->items, it);
488         undo->layer->nitems--;
489       }
490       // recreate the deleted one
491       make_canvas_item_one(undo->layer->group, erasure->item);
492       
493       undo->layer->items = g_list_insert(undo->layer->items, erasure->item,
494                                                              erasure->npos);
495       if (erasure->npos == 0)
496         lower_canvas_item_to(undo->layer->group, erasure->item->canvas_item, NULL);
497       else
498         lower_canvas_item_to(undo->layer->group, erasure->item->canvas_item,
499           ((struct Item *)g_list_nth_data(undo->layer->items, erasure->npos-1))->canvas_item);
500       undo->layer->nitems++;
501     }
502   }
503   else if (undo->type == ITEM_NEW_BG_ONE || undo->type == ITEM_NEW_BG_RESIZE
504            || undo->type == ITEM_PAPER_RESIZE) {
505     if (undo->type != ITEM_PAPER_RESIZE) {
506       // swap the two bg's
507       tmp_bg = undo->page->bg;
508       undo->page->bg = undo->bg;
509       undo->bg = tmp_bg;
510       undo->page->bg->canvas_item = undo->bg->canvas_item;
511       undo->bg->canvas_item = NULL;
512     }
513     if (undo->type != ITEM_NEW_BG_ONE) {
514       tmp_x = undo->page->width;
515       tmp_y = undo->page->height;
516       undo->page->width = undo->val_x;
517       undo->page->height = undo->val_y;
518       undo->val_x = tmp_x;
519       undo->val_y = tmp_y;
520       make_page_clipbox(undo->page);
521     }
522     update_canvas_bg(undo->page);
523     do_switch_page(g_list_index(journal.pages, undo->page), TRUE, TRUE);
524   }
525   else if (undo->type == ITEM_NEW_DEFAULT_BG) {
526     tmp_bg = ui.default_page.bg;
527     ui.default_page.bg = undo->bg;
528     undo->bg = tmp_bg;
529     tmp_x = ui.default_page.width;
530     tmp_y = ui.default_page.height;
531     ui.default_page.width = undo->val_x;
532     ui.default_page.height = undo->val_y;
533     undo->val_x = tmp_x;
534     undo->val_y = tmp_y;
535   }
536   else if (undo->type == ITEM_NEW_PAGE) {
537     // unmap the page; keep the page & its empty layer in memory
538     if (undo->page->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->page->group));
539       // also destroys the background and layer's canvas items
540     undo->page->group = NULL;
541     undo->page->bg->canvas_item = NULL;
542     journal.pages = g_list_remove(journal.pages, undo->page);
543     journal.npages--;
544     if (ui.cur_page == undo->page) ui.cur_page = NULL;
545         // so do_switch_page() won't try to remap the layers of the defunct page
546     if (ui.pageno >= undo->val) ui.pageno--;
547     if (ui.pageno < 0) ui.pageno = 0;
548     do_switch_page(ui.pageno, TRUE, TRUE);
549   }
550   else if (undo->type == ITEM_DELETE_PAGE) {
551     journal.pages = g_list_insert(journal.pages, undo->page, undo->val);
552     journal.npages++;
553     make_canvas_items(); // re-create the canvas items
554     do_switch_page(undo->val, TRUE, TRUE);
555   }
556   else if (undo->type == ITEM_MOVESEL) {
557     for (itemlist = undo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
558       it = (struct Item *)itemlist->data;
559       if (it->canvas_item != NULL) {
560         if (undo->layer != undo->layer2)
561           gnome_canvas_item_reparent(it->canvas_item, undo->layer->group);
562         gnome_canvas_item_move(it->canvas_item, -undo->val_x, -undo->val_y);
563       }
564     }
565     move_journal_items_by(undo->itemlist, -undo->val_x, -undo->val_y,
566                             undo->layer2, undo->layer, undo->auxlist);
567   }
568   else if (undo->type == ITEM_RESIZESEL) {
569     resize_journal_items_by(undo->itemlist, 
570       1/undo->scaling_x, 1/undo->scaling_y,
571       -undo->val_x/undo->scaling_x, -undo->val_y/undo->scaling_y);
572   }
573   else if (undo->type == ITEM_PASTE) {
574     for (itemlist = undo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
575       it = (struct Item *)itemlist->data;
576       gtk_object_destroy(GTK_OBJECT(it->canvas_item));
577       it->canvas_item = NULL;
578       undo->layer->items = g_list_remove(undo->layer->items, it);
579       undo->layer->nitems--;
580     }
581   }
582   else if (undo->type == ITEM_NEW_LAYER) {
583     // unmap the layer; keep the empty layer in memory
584     if (undo->layer->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->layer->group));
585     undo->layer->group = NULL;
586     undo->page->layers = g_list_remove(undo->page->layers, undo->layer);
587     undo->page->nlayers--;
588     do_switch_page(ui.pageno, FALSE, FALSE); // don't stay with bad cur_layer info
589   }
590   else if (undo->type == ITEM_DELETE_LAYER) {
591     // special case of -1: deleted the last layer, created a new one
592     if (undo->val == -1) {
593       if (undo->layer2->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->layer2->group));
594       undo->layer2->group = NULL;
595       undo->page->layers = g_list_remove(undo->page->layers, undo->layer2);
596       undo->page->nlayers--;
597     }
598     // re-map the layer
599     undo->layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
600       undo->page->group, gnome_canvas_group_get_type(), NULL);
601     lower_canvas_item_to(undo->page->group, GNOME_CANVAS_ITEM(undo->layer->group),
602       (undo->val >= 1) ? GNOME_CANVAS_ITEM(((struct Layer *)
603             g_list_nth_data(undo->page->layers, undo->val-1))->group) :
604             undo->page->bg->canvas_item);
605     undo->page->layers = g_list_insert(undo->page->layers, undo->layer,
606                                      (undo->val >= 0) ? undo->val:0);
607     undo->page->nlayers++;
608     
609     for (itemlist = undo->layer->items; itemlist!=NULL; itemlist = itemlist->next)
610       make_canvas_item_one(undo->layer->group, (struct Item *)itemlist->data);
611
612     do_switch_page(ui.pageno, FALSE, FALSE); // show the restored layer & others...
613   }
614   else if (undo->type == ITEM_REPAINTSEL) {
615     for (itemlist = undo->itemlist, list = undo->auxlist; itemlist!=NULL;
616            itemlist = itemlist->next, list = list->next) {
617       it = (struct Item *)itemlist->data;
618       g_memmove(&tmp_brush, &(it->brush), sizeof(struct Brush));
619       g_memmove(&(it->brush), list->data, sizeof(struct Brush));
620       g_memmove(list->data, &tmp_brush, sizeof(struct Brush));
621       if (it->type == ITEM_STROKE && it->canvas_item != NULL) {
622         // remark: a variable-width item might have lost its variable-width
623         group = (GnomeCanvasGroup *) it->canvas_item->parent;
624         gtk_object_destroy(GTK_OBJECT(it->canvas_item));
625         make_canvas_item_one(group, it);
626       }
627       if (it->type == ITEM_TEXT && it->canvas_item != NULL)
628         gnome_canvas_item_set(it->canvas_item, 
629           "fill-color-rgba", it->brush.color_rgba, NULL);
630     }
631   }
632   else if (undo->type == ITEM_TEXT_EDIT) {
633     tmpstr = undo->str;
634     undo->str = undo->item->text;
635     undo->item->text = tmpstr;
636     gnome_canvas_item_set(undo->item->canvas_item, "text", tmpstr, NULL);
637     update_item_bbox(undo->item);
638   }
639   else if (undo->type == ITEM_TEXT_ATTRIB) {
640     tmpstr = undo->str;
641     undo->str = undo->item->font_name;
642     undo->item->font_name = tmpstr;
643     tmp_x = undo->val_x;
644     undo->val_x = undo->item->font_size;
645     undo->item->font_size = tmp_x;
646     g_memmove(&tmp_brush, undo->brush, sizeof(struct Brush));
647     g_memmove(undo->brush, &(undo->item->brush), sizeof(struct Brush));
648     g_memmove(&(undo->item->brush), &tmp_brush, sizeof(struct Brush));
649     gnome_canvas_item_set(undo->item->canvas_item, 
650       "fill-color-rgba", undo->item->brush.color_rgba, NULL);
651     update_text_item_displayfont(undo->item);
652     update_item_bbox(undo->item);
653   }
654   
655   // move item from undo to redo stack
656   u = undo;
657   undo = undo->next;
658   u->next = redo;
659   redo = u;
660   ui.saved = FALSE;
661   update_undo_redo_enabled();
662   if (u->multiop & MULTIOP_CONT_UNDO) on_editUndo_activate(NULL,NULL); // loop
663 }
664
665
666 void
667 on_editRedo_activate                   (GtkMenuItem     *menuitem,
668                                         gpointer         user_data)
669 {
670   struct UndoItem *u;
671   GList *list, *itemlist, *target;
672   struct UndoErasureData *erasure;
673   struct Item *it;
674   struct Brush tmp_brush;
675   struct Background *tmp_bg;
676   struct Layer *l;
677   double tmp_x, tmp_y;
678   gchar *tmpstr;
679   GnomeCanvasGroup *group;
680   
681   end_text();
682   if (redo == NULL) return; // nothing to redo!
683   reset_selection(); // safer
684   reset_recognizer(); // safer
685   if (redo->type == ITEM_STROKE || redo->type == ITEM_TEXT) {
686     // re-create the canvas_item
687     make_canvas_item_one(redo->layer->group, redo->item);
688     // reinsert the item on its layer
689     redo->layer->items = g_list_append(redo->layer->items, redo->item);
690     redo->layer->nitems++;
691   }
692   else if (redo->type == ITEM_ERASURE || redo->type == ITEM_RECOGNIZER) {
693     for (list = redo->erasurelist; list!=NULL; list = list->next) {
694       erasure = (struct UndoErasureData *)list->data;
695       target = g_list_find(redo->layer->items, erasure->item);
696       // re-create all the created items
697       for (itemlist = erasure->replacement_items; itemlist!=NULL; itemlist = itemlist->next) {
698         it = (struct Item *)itemlist->data;
699         make_canvas_item_one(redo->layer->group, it);
700         redo->layer->items = g_list_insert_before(redo->layer->items, target, it);
701         redo->layer->nitems++;
702         lower_canvas_item_to(redo->layer->group, it->canvas_item, erasure->item->canvas_item);
703       }
704       // re-delete the deleted one
705       gtk_object_destroy(GTK_OBJECT(erasure->item->canvas_item));
706       erasure->item->canvas_item = NULL;
707       redo->layer->items = g_list_delete_link(redo->layer->items, target);
708       redo->layer->nitems--;
709     }
710   }
711   else if (redo->type == ITEM_NEW_BG_ONE || redo->type == ITEM_NEW_BG_RESIZE
712            || redo->type == ITEM_PAPER_RESIZE) {
713     if (redo->type != ITEM_PAPER_RESIZE) {
714       // swap the two bg's
715       tmp_bg = redo->page->bg;
716       redo->page->bg = redo->bg;
717       redo->bg = tmp_bg;
718       redo->page->bg->canvas_item = redo->bg->canvas_item;
719       redo->bg->canvas_item = NULL;
720     }
721     if (redo->type != ITEM_NEW_BG_ONE) {
722       tmp_x = redo->page->width;
723       tmp_y = redo->page->height;
724       redo->page->width = redo->val_x;
725       redo->page->height = redo->val_y;
726       redo->val_x = tmp_x;
727       redo->val_y = tmp_y;
728       make_page_clipbox(redo->page);
729     }
730     update_canvas_bg(redo->page);
731     do_switch_page(g_list_index(journal.pages, redo->page), TRUE, TRUE);
732   }
733   else if (redo->type == ITEM_NEW_DEFAULT_BG) {
734     tmp_bg = ui.default_page.bg;
735     ui.default_page.bg = redo->bg;
736     redo->bg = tmp_bg;
737     tmp_x = ui.default_page.width;
738     tmp_y = ui.default_page.height;
739     ui.default_page.width = redo->val_x;
740     ui.default_page.height = redo->val_y;
741     redo->val_x = tmp_x;
742     redo->val_y = tmp_y;
743   }
744   else if (redo->type == ITEM_NEW_PAGE) {
745     // remap the page
746     redo->page->bg->canvas_item = NULL;
747     redo->page->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
748       gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
749     make_page_clipbox(redo->page);
750     update_canvas_bg(redo->page);
751     l = (struct Layer *)redo->page->layers->data;
752     l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
753       redo->page->group, gnome_canvas_group_get_type(), NULL);
754     
755     journal.pages = g_list_insert(journal.pages, redo->page, redo->val);
756     journal.npages++;
757     do_switch_page(redo->val, TRUE, TRUE);
758   }
759   else if (redo->type == ITEM_DELETE_PAGE) {
760     // unmap all the canvas items
761     gtk_object_destroy(GTK_OBJECT(redo->page->group));
762     redo->page->group = NULL;
763     redo->page->bg->canvas_item = NULL;
764     for (list = redo->page->layers; list!=NULL; list = list->next) {
765       l = (struct Layer *)list->data;
766       for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next)
767         ((struct Item *)itemlist->data)->canvas_item = NULL;
768       l->group = NULL;
769     }
770     journal.pages = g_list_remove(journal.pages, redo->page);
771     journal.npages--;
772     if (ui.pageno > redo->val || ui.pageno == journal.npages) ui.pageno--;
773     ui.cur_page = NULL;
774       // so do_switch_page() won't try to remap the layers of the defunct page
775     do_switch_page(ui.pageno, TRUE, TRUE);
776   }
777   else if (redo->type == ITEM_MOVESEL) {
778     for (itemlist = redo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
779       it = (struct Item *)itemlist->data;
780       if (it->canvas_item != NULL) {
781         if (redo->layer != redo->layer2)
782           gnome_canvas_item_reparent(it->canvas_item, redo->layer2->group);
783         gnome_canvas_item_move(it->canvas_item, redo->val_x, redo->val_y);
784       }
785     }
786     move_journal_items_by(redo->itemlist, redo->val_x, redo->val_y,
787                             redo->layer, redo->layer2, NULL);
788   }
789   else if (redo->type == ITEM_RESIZESEL) {
790     resize_journal_items_by(redo->itemlist, 
791           redo->scaling_x, redo->scaling_y, redo->val_x, redo->val_y);
792   }
793   else if (redo->type == ITEM_PASTE) {
794     for (itemlist = redo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
795       it = (struct Item *)itemlist->data;
796       make_canvas_item_one(redo->layer->group, it);
797       redo->layer->items = g_list_append(redo->layer->items, it);
798       redo->layer->nitems++;
799     }
800   }
801   else if (redo->type == ITEM_NEW_LAYER) {
802     redo->layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
803         redo->page->group, gnome_canvas_group_get_type(), NULL);
804     lower_canvas_item_to(redo->page->group, GNOME_CANVAS_ITEM(redo->layer->group),
805       (redo->val >= 1) ? GNOME_CANVAS_ITEM(((struct Layer *)
806             g_list_nth_data(redo->page->layers, redo->val-1))->group) :
807             redo->page->bg->canvas_item);
808     redo->page->layers = g_list_insert(redo->page->layers, redo->layer, redo->val);
809     redo->page->nlayers++;
810     do_switch_page(ui.pageno, FALSE, FALSE);
811   }
812   else if (redo->type == ITEM_DELETE_LAYER) {
813     gtk_object_destroy(GTK_OBJECT(redo->layer->group));
814     redo->layer->group = NULL;
815     for (list=redo->layer->items; list!=NULL; list=list->next)
816       ((struct Item *)list->data)->canvas_item = NULL;
817     redo->page->layers = g_list_remove(redo->page->layers, redo->layer);
818     redo->page->nlayers--;
819     if (redo->val == -1) {
820       redo->layer2->group = (GnomeCanvasGroup *)gnome_canvas_item_new(
821         redo->page->group, gnome_canvas_group_get_type(), NULL);
822       redo->page->layers = g_list_append(redo->page->layers, redo->layer2);
823       redo->page->nlayers++;
824     }
825     do_switch_page(ui.pageno, FALSE, FALSE);
826   }
827   else if (redo->type == ITEM_REPAINTSEL) {
828     for (itemlist = redo->itemlist, list = redo->auxlist; itemlist!=NULL;
829            itemlist = itemlist->next, list = list->next) {
830       it = (struct Item *)itemlist->data;
831       g_memmove(&tmp_brush, &(it->brush), sizeof(struct Brush));
832       g_memmove(&(it->brush), list->data, sizeof(struct Brush));
833       g_memmove(list->data, &tmp_brush, sizeof(struct Brush));
834       if (it->type == ITEM_STROKE && it->canvas_item != NULL) {
835         // remark: a variable-width item might have lost its variable-width
836         group = (GnomeCanvasGroup *) it->canvas_item->parent;
837         gtk_object_destroy(GTK_OBJECT(it->canvas_item));
838         make_canvas_item_one(group, it);
839       }
840       if (it->type == ITEM_TEXT && it->canvas_item != NULL)
841         gnome_canvas_item_set(it->canvas_item, 
842           "fill-color-rgba", it->brush.color_rgba, NULL);
843     }
844   }
845   else if (redo->type == ITEM_TEXT_EDIT) {
846     tmpstr = redo->str;
847     redo->str = redo->item->text;
848     redo->item->text = tmpstr;
849     gnome_canvas_item_set(redo->item->canvas_item, "text", tmpstr, NULL);
850     update_item_bbox(redo->item);
851   }
852   else if (redo->type == ITEM_TEXT_ATTRIB) {
853     tmpstr = redo->str;
854     redo->str = redo->item->font_name;
855     redo->item->font_name = tmpstr;
856     tmp_x = redo->val_x;
857     redo->val_x = redo->item->font_size;
858     redo->item->font_size = tmp_x;
859     g_memmove(&tmp_brush, redo->brush, sizeof(struct Brush));
860     g_memmove(redo->brush, &(redo->item->brush), sizeof(struct Brush));
861     g_memmove(&(redo->item->brush), &tmp_brush, sizeof(struct Brush));
862     gnome_canvas_item_set(redo->item->canvas_item, 
863       "fill-color-rgba", redo->item->brush.color_rgba, NULL);
864     update_text_item_displayfont(redo->item);
865     update_item_bbox(redo->item);
866   }
867   
868   // move item from redo to undo stack
869   u = redo;
870   redo = redo->next;
871   u->next = undo;
872   undo = u;
873   ui.saved = FALSE;
874   update_undo_redo_enabled();
875   if (u->multiop & MULTIOP_CONT_REDO) on_editRedo_activate(NULL,NULL); // loop
876 }
877
878
879 void
880 on_editCut_activate                    (GtkMenuItem     *menuitem,
881                                         gpointer         user_data)
882 {
883   end_text();
884   selection_to_clip();
885   selection_delete();
886 }
887
888
889 void
890 on_editCopy_activate                   (GtkMenuItem     *menuitem,
891                                         gpointer         user_data)
892 {
893   end_text();
894   selection_to_clip();
895 }
896
897
898 void
899 on_editPaste_activate                  (GtkMenuItem     *menuitem,
900                                         gpointer         user_data)
901 {
902   end_text();
903   clipboard_paste();
904 }
905
906
907 void
908 on_editDelete_activate                 (GtkMenuItem     *menuitem,
909                                         gpointer         user_data)
910 {
911   end_text();
912   selection_delete();
913 }
914
915
916 void
917 on_viewContinuous_activate             (GtkMenuItem     *menuitem,
918                                         gpointer         user_data)
919 {
920   GtkAdjustment *v_adj;
921   double yscroll;
922   struct Page *pg;
923
924   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
925   if (ui.view_continuous) return;
926   ui.view_continuous = TRUE;
927   v_adj = gtk_layout_get_vadjustment(GTK_LAYOUT(canvas));
928   pg = ui.cur_page;
929   yscroll = gtk_adjustment_get_value(v_adj) - pg->voffset*ui.zoom;
930   update_page_stuff();
931   gtk_adjustment_set_value(v_adj, yscroll + pg->voffset*ui.zoom);
932   // force a refresh
933   gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
934 }
935
936
937 void
938 on_viewOnePage_activate                (GtkMenuItem     *menuitem,
939                                         gpointer         user_data)
940 {
941   GtkAdjustment *v_adj;
942   double yscroll;
943   
944   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
945   if (!ui.view_continuous) return;
946   ui.view_continuous = FALSE;
947   v_adj = gtk_layout_get_vadjustment(GTK_LAYOUT(canvas));
948   yscroll = gtk_adjustment_get_value(v_adj) - ui.cur_page->voffset*ui.zoom;
949   update_page_stuff();
950   gtk_adjustment_set_value(v_adj, yscroll + ui.cur_page->voffset*ui.zoom);
951   // force a refresh
952   gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
953 }
954
955
956 void
957 on_viewZoomIn_activate                 (GtkMenuItem     *menuitem,
958                                         gpointer         user_data)
959 {
960   if (ui.zoom > MAX_ZOOM) return;
961   ui.zoom *= ui.zoom_step_factor;
962   gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
963   rescale_text_items();
964   rescale_bg_pixmaps();
965 }
966
967
968 void
969 on_viewZoomOut_activate                (GtkMenuItem     *menuitem,
970                                         gpointer         user_data)
971 {
972   if (ui.zoom < MIN_ZOOM) return;
973   ui.zoom /= ui.zoom_step_factor;
974   gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
975   rescale_text_items();
976   rescale_bg_pixmaps();
977 }
978
979
980 void
981 on_viewNormalSize_activate             (GtkMenuItem     *menuitem,
982                                         gpointer         user_data)
983 {
984   ui.zoom = DEFAULT_ZOOM;
985   gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
986   rescale_text_items();
987   rescale_bg_pixmaps();
988 }
989
990
991 void
992 on_viewPageWidth_activate              (GtkMenuItem     *menuitem,
993                                         gpointer         user_data)
994 {
995   ui.zoom = (GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width;
996   gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
997   rescale_text_items();
998   rescale_bg_pixmaps();
999 }
1000
1001
1002 void
1003 on_viewFirstPage_activate              (GtkMenuItem     *menuitem,
1004                                         gpointer         user_data)
1005 {
1006   end_text();
1007   do_switch_page(0, TRUE, FALSE);
1008 }
1009
1010
1011 void
1012 on_viewPreviousPage_activate           (GtkMenuItem     *menuitem,
1013                                         gpointer         user_data)
1014 {
1015   end_text();
1016   if (ui.pageno == 0) return;
1017   do_switch_page(ui.pageno-1, TRUE, FALSE);
1018 }
1019
1020
1021 void
1022 on_viewNextPage_activate               (GtkMenuItem     *menuitem,
1023                                         gpointer         user_data)
1024 {
1025   end_text();
1026   if (ui.pageno == journal.npages-1) { // create a page at end
1027     on_journalNewPageEnd_activate(menuitem, user_data);
1028     return;
1029   }
1030   do_switch_page(ui.pageno+1, TRUE, FALSE);
1031 }
1032
1033
1034 void
1035 on_viewLastPage_activate               (GtkMenuItem     *menuitem,
1036                                         gpointer         user_data)
1037 {
1038   end_text();
1039   do_switch_page(journal.npages-1, TRUE, FALSE);
1040 }
1041
1042
1043 void
1044 on_viewShowLayer_activate              (GtkMenuItem     *menuitem,
1045                                         gpointer         user_data)
1046 {
1047   end_text();
1048   if (ui.layerno == ui.cur_page->nlayers-1) return;
1049   reset_selection();
1050   ui.layerno++;
1051   ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
1052   gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group));
1053   update_page_stuff();
1054 }
1055
1056
1057 void
1058 on_viewHideLayer_activate              (GtkMenuItem     *menuitem,
1059                                         gpointer         user_data)
1060 {
1061   end_text();
1062   if (ui.layerno == -1) return;
1063   reset_selection();
1064   gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group));
1065   ui.layerno--;
1066   if (ui.layerno<0) ui.cur_layer = NULL;
1067   else ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
1068   update_page_stuff();
1069 }
1070
1071
1072 void
1073 on_journalNewPageBefore_activate       (GtkMenuItem     *menuitem,
1074                                         gpointer         user_data)
1075 {
1076   struct Page *pg;
1077
1078   end_text();
1079   reset_selection();
1080   pg = new_page(ui.cur_page);
1081   journal.pages = g_list_insert(journal.pages, pg, ui.pageno);
1082   journal.npages++;
1083   do_switch_page(ui.pageno, TRUE, TRUE);
1084   
1085   prepare_new_undo();
1086   undo->type = ITEM_NEW_PAGE;
1087   undo->val = ui.pageno;
1088   undo->page = pg;
1089 }
1090
1091
1092 void
1093 on_journalNewPageAfter_activate        (GtkMenuItem     *menuitem,
1094                                         gpointer         user_data)
1095 {
1096   struct Page *pg;
1097
1098   end_text();
1099   reset_selection();
1100   pg = new_page(ui.cur_page);
1101   journal.pages = g_list_insert(journal.pages, pg, ui.pageno+1);
1102   journal.npages++;
1103   do_switch_page(ui.pageno+1, TRUE, TRUE);
1104
1105   prepare_new_undo();
1106   undo->type = ITEM_NEW_PAGE;
1107   undo->val = ui.pageno;
1108   undo->page = pg;
1109 }
1110
1111
1112 void
1113 on_journalNewPageEnd_activate          (GtkMenuItem     *menuitem,
1114                                         gpointer         user_data)
1115 {
1116   struct Page *pg;
1117
1118   end_text();
1119   reset_selection();
1120   pg = new_page((struct Page *)g_list_last(journal.pages)->data);
1121   journal.pages = g_list_append(journal.pages, pg);
1122   journal.npages++;
1123   do_switch_page(journal.npages-1, TRUE, TRUE);
1124
1125   prepare_new_undo();
1126   undo->type = ITEM_NEW_PAGE;
1127   undo->val = ui.pageno;
1128   undo->page = pg;
1129 }
1130
1131
1132 void
1133 on_journalDeletePage_activate          (GtkMenuItem     *menuitem,
1134                                         gpointer         user_data)
1135 {
1136   GList *layerlist, *itemlist;
1137   struct Layer *l;
1138
1139   end_text();
1140   if (journal.npages == 1) return;
1141   reset_selection();  
1142   reset_recognizer(); // safer
1143   prepare_new_undo();
1144   undo->type = ITEM_DELETE_PAGE;
1145   undo->val = ui.pageno;
1146   undo->page = ui.cur_page;
1147
1148   // unmap all the canvas items  
1149   gtk_object_destroy(GTK_OBJECT(ui.cur_page->group));
1150   ui.cur_page->group = NULL;
1151   ui.cur_page->bg->canvas_item = NULL;
1152   for (layerlist = ui.cur_page->layers; layerlist!=NULL; layerlist = layerlist->next) {
1153     l = (struct Layer *)layerlist->data;
1154     for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next)
1155       ((struct Item *)itemlist->data)->canvas_item = NULL;
1156     l->group = NULL;
1157   }
1158   
1159   journal.pages = g_list_remove(journal.pages, ui.cur_page);
1160   journal.npages--;
1161   if (ui.pageno == journal.npages) ui.pageno--;
1162   ui.cur_page = NULL;
1163      // so do_switch_page() won't try to remap the layers of the defunct page
1164   do_switch_page(ui.pageno, TRUE, TRUE);
1165 }
1166
1167
1168 void
1169 on_journalNewLayer_activate            (GtkMenuItem     *menuitem,
1170                                         gpointer         user_data)
1171 {
1172   struct Layer *l;
1173   
1174   end_text();
1175   reset_selection();
1176   l = g_new(struct Layer, 1);
1177   l->items = NULL;
1178   l->nitems = 0;
1179   l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
1180     ui.cur_page->group, gnome_canvas_group_get_type(), NULL);
1181   lower_canvas_item_to(ui.cur_page->group, GNOME_CANVAS_ITEM(l->group),
1182     (ui.cur_layer!=NULL)?(GNOME_CANVAS_ITEM(ui.cur_layer->group)):(ui.cur_page->bg->canvas_item));
1183   ui.cur_page->layers = g_list_insert(ui.cur_page->layers, l, ui.layerno+1);
1184   ui.cur_layer = l;
1185   ui.layerno++;
1186   ui.cur_page->nlayers++;
1187   update_page_stuff();
1188
1189   prepare_new_undo();
1190   undo->type = ITEM_NEW_LAYER;
1191   undo->val = ui.layerno;
1192   undo->layer = l;
1193   undo->page = ui.cur_page;  
1194 }
1195
1196
1197 void
1198 on_journalDeleteLayer_activate         (GtkMenuItem     *menuitem,
1199                                         gpointer         user_data)
1200 {
1201   GList *list;
1202   
1203   end_text();
1204   if (ui.cur_layer == NULL) return;
1205   reset_selection();
1206   reset_recognizer(); // safer
1207   prepare_new_undo();
1208   undo->type = ITEM_DELETE_LAYER;
1209   undo->val = ui.layerno;
1210   undo->layer = ui.cur_layer;
1211   undo->layer2 = NULL;
1212   undo->page = ui.cur_page;
1213   // delete all the canvas items
1214   gtk_object_destroy(GTK_OBJECT(ui.cur_layer->group));
1215   ui.cur_layer->group = NULL;
1216   for (list=ui.cur_layer->items; list!=NULL; list=list->next)
1217     ((struct Item *)list->data)->canvas_item = NULL;
1218
1219   ui.cur_page->layers = g_list_remove(ui.cur_page->layers, ui.cur_layer);
1220
1221   if (ui.cur_page->nlayers>=2) {
1222     ui.cur_page->nlayers--;
1223     ui.layerno--;
1224     if (ui.layerno<0) ui.cur_layer = NULL;
1225     else ui.cur_layer = (struct Layer *)g_list_nth_data(ui.cur_page->layers, ui.layerno);
1226   } 
1227   else { // special case: can't remove the last layer
1228     ui.cur_layer = g_new(struct Layer, 1);
1229     ui.cur_layer->items = NULL;
1230     ui.cur_layer->nitems = 0;
1231     ui.cur_layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
1232       ui.cur_page->group, gnome_canvas_group_get_type(), NULL);
1233     ui.cur_page->layers = g_list_append(NULL, ui.cur_layer);
1234     undo->val = -1;
1235     undo->layer2 = ui.cur_layer;
1236   }
1237
1238   update_page_stuff();
1239 }
1240
1241
1242 void
1243 on_journalFlatten_activate             (GtkMenuItem     *menuitem,
1244                                         gpointer         user_data)
1245 {
1246
1247 }
1248
1249
1250 // the paper sizes dialog
1251
1252 GtkWidget *papersize_dialog;
1253 int papersize_std, papersize_unit;
1254 double papersize_width, papersize_height;
1255 gboolean papersize_need_init, papersize_width_valid, papersize_height_valid;
1256
1257 #define STD_SIZE_A4 0
1258 #define STD_SIZE_A4R 1
1259 #define STD_SIZE_LETTER 2
1260 #define STD_SIZE_LETTER_R 3
1261 #define STD_SIZE_CUSTOM 4
1262
1263 double unit_sizes[4] = {28.346, 72., 72./DISPLAY_DPI_DEFAULT, 1.};
1264 double std_widths[STD_SIZE_CUSTOM] =  {595.27, 841.89, 612., 792.};
1265 double std_heights[STD_SIZE_CUSTOM] = {841.89, 595.27, 792., 612.};
1266 double std_units[STD_SIZE_CUSTOM] = {UNIT_CM, UNIT_CM, UNIT_IN, UNIT_IN};
1267
1268 void
1269 on_journalPaperSize_activate           (GtkMenuItem     *menuitem,
1270                                         gpointer         user_data)
1271 {
1272   int i, response;
1273   struct Page *pg;
1274   GList *pglist;
1275   
1276   end_text();
1277   papersize_dialog = create_papersizeDialog();
1278   papersize_width = ui.cur_page->width;
1279   papersize_height = ui.cur_page->height;
1280   papersize_unit = ui.default_unit;
1281   unit_sizes[UNIT_PX] = 1./DEFAULT_ZOOM;
1282 //  if (ui.cur_page->bg->type == BG_PIXMAP) papersize_unit = UNIT_PX;
1283   papersize_std = STD_SIZE_CUSTOM;
1284   for (i=0;i<STD_SIZE_CUSTOM;i++)
1285     if (fabs(papersize_width - std_widths[i])<0.1 &&
1286         fabs(papersize_height - std_heights[i])<0.1)
1287       { papersize_std = i; papersize_unit = std_units[i]; }
1288   papersize_need_init = TRUE;
1289   papersize_width_valid = papersize_height_valid = TRUE;
1290       
1291   gtk_widget_show(papersize_dialog);
1292   on_comboStdSizes_changed(GTK_COMBO_BOX(g_object_get_data(
1293        G_OBJECT(papersize_dialog), "comboStdSizes")), NULL);
1294   gtk_dialog_set_default_response(GTK_DIALOG(papersize_dialog), GTK_RESPONSE_OK);
1295        
1296   response = gtk_dialog_run(GTK_DIALOG(papersize_dialog));
1297   gtk_widget_destroy(papersize_dialog);
1298   if (response != GTK_RESPONSE_OK) return;
1299
1300   pg = ui.cur_page;
1301   for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
1302     if (ui.bg_apply_all_pages) pg = (struct Page *)pglist->data;
1303     prepare_new_undo();
1304     if (ui.bg_apply_all_pages) {
1305       if (pglist->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
1306       if (pglist->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
1307     }
1308     undo->type = ITEM_PAPER_RESIZE;
1309     undo->page = pg;
1310     undo->val_x = pg->width;
1311     undo->val_y = pg->height;
1312     if (papersize_width_valid) pg->width = papersize_width;
1313     if (papersize_height_valid) pg->height = papersize_height;
1314     make_page_clipbox(pg);
1315     update_canvas_bg(pg);
1316     if (!ui.bg_apply_all_pages) break;
1317   }
1318   do_switch_page(ui.pageno, TRUE, TRUE);
1319 }
1320
1321
1322 void
1323 on_papercolorWhite_activate            (GtkMenuItem     *menuitem,
1324                                         gpointer         user_data)
1325 {
1326   end_text();
1327   process_papercolor_activate(menuitem, COLOR_WHITE, predef_bgcolors_rgba[COLOR_WHITE]);
1328 }
1329
1330
1331 void
1332 on_papercolorYellow_activate           (GtkMenuItem     *menuitem,
1333                                         gpointer         user_data)
1334 {
1335   end_text();
1336   process_papercolor_activate(menuitem, COLOR_YELLOW, predef_bgcolors_rgba[COLOR_YELLOW]);
1337 }
1338
1339
1340 void
1341 on_papercolorPink_activate             (GtkMenuItem     *menuitem,
1342                                         gpointer         user_data)
1343 {
1344   end_text();
1345   process_papercolor_activate(menuitem, COLOR_RED, predef_bgcolors_rgba[COLOR_RED]);
1346 }
1347
1348
1349 void
1350 on_papercolorOrange_activate           (GtkMenuItem     *menuitem,
1351                                         gpointer         user_data)
1352 {
1353   end_text();
1354   process_papercolor_activate(menuitem, COLOR_ORANGE, predef_bgcolors_rgba[COLOR_ORANGE]);
1355 }
1356
1357
1358 void
1359 on_papercolorBlue_activate             (GtkMenuItem     *menuitem,
1360                                         gpointer         user_data)
1361 {
1362   end_text();
1363   process_papercolor_activate(menuitem, COLOR_BLUE, predef_bgcolors_rgba[COLOR_BLUE]);
1364 }
1365
1366
1367 void
1368 on_papercolorGreen_activate            (GtkMenuItem     *menuitem,
1369                                         gpointer         user_data)
1370 {
1371   end_text();
1372   process_papercolor_activate(menuitem, COLOR_GREEN, predef_bgcolors_rgba[COLOR_GREEN]);
1373 }
1374
1375
1376 void
1377 on_papercolorOther_activate            (GtkMenuItem     *menuitem,
1378                                         gpointer         user_data)
1379 {
1380   GtkWidget *dialog;
1381   GtkColorSelection *colorsel;
1382   gint result;
1383   guint rgba;
1384   GdkColor gdkcolor;
1385   
1386   end_text();
1387   dialog = gtk_color_selection_dialog_new(_("Pick a Paper Color"));
1388   colorsel = GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(dialog)->colorsel);
1389   if (ui.cur_page->bg->type == BG_SOLID) rgba = ui.cur_page->bg->color_rgba;
1390   else rgba = ui.default_page.bg->color_rgba;
1391   rgb_to_gdkcolor(rgba, &gdkcolor);
1392   gtk_color_selection_set_current_color(colorsel, &gdkcolor);
1393   
1394   if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) {
1395     gtk_color_selection_get_current_color(colorsel, &gdkcolor);
1396     process_papercolor_activate(menuitem, COLOR_OTHER, gdkcolor_to_rgba(gdkcolor, 0xffff));
1397   }
1398   gtk_widget_destroy(dialog);
1399 }
1400
1401
1402 void
1403 on_paperstylePlain_activate            (GtkMenuItem     *menuitem,
1404                                         gpointer         user_data)
1405 {
1406   end_text();
1407   process_paperstyle_activate(menuitem, RULING_NONE);
1408 }
1409
1410
1411 void
1412 on_paperstyleLined_activate            (GtkMenuItem     *menuitem,
1413                                         gpointer         user_data)
1414 {
1415   end_text();
1416   process_paperstyle_activate(menuitem, RULING_LINED);
1417 }
1418
1419
1420 void
1421 on_paperstyleRuled_activate            (GtkMenuItem     *menuitem,
1422                                         gpointer         user_data)
1423 {
1424   end_text();
1425   process_paperstyle_activate(menuitem, RULING_RULED);
1426 }
1427
1428
1429 void
1430 on_paperstyleGraph_activate            (GtkMenuItem     *menuitem,
1431                                         gpointer         user_data)
1432 {
1433   end_text();
1434   process_paperstyle_activate(menuitem, RULING_GRAPH);
1435 }
1436
1437
1438 void
1439 on_journalLoadBackground_activate      (GtkMenuItem     *menuitem,
1440                                         gpointer         user_data)
1441 {
1442   GtkWidget *dialog, *attach_opt;
1443   struct Background *bg;
1444   struct Page *pg;
1445   int pageno;
1446   GList *bglist, *bglistiter;
1447   GtkFileFilter *filt_all, *filt_pix, *filt_pspdf;
1448   char *filename;
1449   gboolean attach;
1450   
1451   end_text();
1452   dialog = gtk_file_chooser_dialog_new(_("Open Background"), GTK_WINDOW (winMain),
1453      GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1454      GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
1455 #ifdef FILE_DIALOG_SIZE_BUGFIX
1456   gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
1457 #endif
1458
1459   filt_all = gtk_file_filter_new();
1460   gtk_file_filter_set_name(filt_all, _("All files"));
1461   gtk_file_filter_add_pattern(filt_all, "*");
1462   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
1463
1464 #if GTK_CHECK_VERSION(2,6,0)
1465
1466   if (!gtk_check_version(2, 6, 0)) {
1467     filt_pix = gtk_file_filter_new();
1468     gtk_file_filter_set_name(filt_pix, _("Bitmap files"));
1469     gtk_file_filter_add_pixbuf_formats(filt_pix);
1470     gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pix);
1471   }
1472   
1473 #endif
1474
1475   filt_pspdf = gtk_file_filter_new();
1476   gtk_file_filter_set_name(filt_pspdf, _("PS/PDF files (as bitmaps)"));
1477   gtk_file_filter_add_pattern(filt_pspdf, "*.ps");
1478   gtk_file_filter_add_pattern(filt_pspdf, "*.PS");
1479   gtk_file_filter_add_pattern(filt_pspdf, "*.pdf");
1480   gtk_file_filter_add_pattern(filt_pspdf, "*.PDF");
1481   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pspdf);
1482
1483   attach_opt = gtk_check_button_new_with_label(_("Attach file to the journal"));
1484   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(attach_opt), FALSE);
1485   gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER (dialog), attach_opt);
1486
1487   if (ui.default_path!=NULL) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
1488   
1489   if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
1490     gtk_widget_destroy(dialog);
1491     return;
1492   }
1493   filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1494   attach = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(attach_opt));
1495   gtk_widget_destroy(dialog);
1496   
1497   set_cursor_busy(TRUE);
1498   bg = attempt_load_pix_bg(filename, attach);
1499   if (bg != NULL) bglist = g_list_append(NULL, bg);
1500   else bglist = attempt_load_gv_bg(filename);
1501   set_cursor_busy(FALSE);
1502   
1503   if (bglist == NULL) {
1504     dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL,
1505       GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
1506       _("Error opening background '%s'"), filename);
1507     gtk_dialog_run(GTK_DIALOG(dialog));
1508     gtk_widget_destroy(dialog);
1509     g_free(filename);
1510     return;
1511   }
1512
1513   g_free(filename);
1514   reset_selection();
1515   pageno = ui.pageno;
1516
1517   for (bglistiter = bglist, pageno = ui.pageno; 
1518            bglistiter!=NULL; bglistiter = bglistiter->next, pageno++) {
1519     prepare_new_undo();
1520     if (bglistiter->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
1521     if (bglistiter->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
1522
1523     bg = (struct Background *)bglistiter->data;
1524     
1525     if (pageno == journal.npages) {
1526       undo->type = ITEM_NEW_PAGE;
1527       pg = new_page_with_bg(bg, 
1528               gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale,
1529               gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale);
1530       journal.pages = g_list_append(journal.pages, pg);
1531       journal.npages++;
1532       undo->val = pageno;
1533       undo->page = pg;
1534     } else
1535     {
1536       pg = g_list_nth_data(journal.pages, pageno);
1537       undo->type = ITEM_NEW_BG_RESIZE;
1538       undo->page = pg;
1539       undo->bg = pg->bg;
1540       bg->canvas_item = undo->bg->canvas_item;
1541       undo->bg->canvas_item = NULL;
1542       undo->val_x = pg->width;
1543       undo->val_y = pg->height;
1544       pg->bg = bg;
1545       pg->width = gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale;
1546       pg->height = gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale;
1547       make_page_clipbox(pg);
1548       update_canvas_bg(pg);
1549     }
1550   }
1551
1552   g_list_free(bglist);
1553   if (ui.zoom != DEFAULT_ZOOM) {
1554     ui.zoom = DEFAULT_ZOOM;
1555     gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
1556     rescale_text_items();
1557     rescale_bg_pixmaps();
1558   }
1559   do_switch_page(ui.pageno, TRUE, TRUE);
1560 }
1561
1562 void
1563 on_journalScreenshot_activate          (GtkMenuItem     *menuitem,
1564                                         gpointer         user_data)
1565 {
1566   struct Background *bg;
1567   
1568   end_text();
1569   reset_selection();
1570   gtk_window_iconify(GTK_WINDOW(winMain)); // hide ourselves
1571   gdk_display_sync(gdk_display_get_default());
1572
1573   if (ui.cursor!=NULL)
1574     gdk_cursor_unref(ui.cursor);
1575   ui.cursor = gdk_cursor_new(GDK_TCROSS);
1576
1577   bg = attempt_screenshot_bg();
1578     
1579   gtk_window_deiconify(GTK_WINDOW(winMain));
1580   update_cursor();
1581   if (bg==NULL) return;
1582
1583   prepare_new_undo();
1584   undo->type = ITEM_NEW_BG_RESIZE;
1585   undo->page = ui.cur_page;
1586   undo->bg = ui.cur_page->bg;
1587   bg->canvas_item = undo->bg->canvas_item;
1588   undo->bg->canvas_item = NULL;
1589   undo->val_x = ui.cur_page->width;
1590   undo->val_y = ui.cur_page->height;
1591
1592   ui.cur_page->bg = bg;
1593   ui.cur_page->width = gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale;
1594   ui.cur_page->height = gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale;
1595
1596   make_page_clipbox(ui.cur_page);
1597   update_canvas_bg(ui.cur_page);
1598
1599   if (ui.zoom != DEFAULT_ZOOM) {
1600     ui.zoom = DEFAULT_ZOOM;
1601     gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
1602     rescale_text_items();
1603     rescale_bg_pixmaps();
1604   }
1605   do_switch_page(ui.pageno, TRUE, TRUE);
1606 }
1607
1608
1609 void
1610 on_journalApplyAllPages_activate       (GtkMenuItem     *menuitem,
1611                                         gpointer         user_data)
1612 {
1613   gboolean active;
1614   
1615   end_text();
1616   active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
1617   if (active == ui.bg_apply_all_pages) return;
1618   ui.bg_apply_all_pages = active;
1619   update_page_stuff();
1620   
1621 /* THIS IS THE OLD VERSION OF THE FEATURE -- APPLIED CURRENT BG TO ALL
1622   struct Page *page;
1623   GList *pglist;
1624   
1625   if (ui.cur_page->bg->type != BG_SOLID) return;
1626   reset_selection();
1627   for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
1628     page = (struct Page *)pglist->data;
1629     prepare_new_undo();
1630     undo->type = ITEM_NEW_BG_RESIZE;
1631     undo->page = page;
1632     undo->bg = page->bg;
1633     undo->val_x = page->width;
1634     undo->val_y = page->height; 
1635     if (pglist->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
1636     if (pglist->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
1637     page->bg = (struct Background *)g_memdup(ui.cur_page->bg, sizeof(struct Background));
1638     page->width = ui.cur_page->width;
1639     page->height = ui.cur_page->height;
1640     page->bg->canvas_item = undo->bg->canvas_item;
1641     undo->bg->canvas_item = NULL;
1642   
1643     make_page_clipbox(page);
1644     update_canvas_bg(page);
1645   }
1646   do_switch_page(ui.pageno, TRUE, TRUE);
1647 */
1648
1649 }
1650
1651
1652 void
1653 on_toolsPen_activate                   (GtkMenuItem     *menuitem,
1654                                         gpointer         user_data)
1655 {
1656   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1657     if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1658       return;
1659   } else {
1660     if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1661       return;
1662   }
1663   
1664   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1665   if (ui.toolno[ui.cur_mapping] == TOOL_PEN) return;
1666
1667   ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1668   end_text();
1669   reset_selection();
1670   ui.toolno[ui.cur_mapping] = TOOL_PEN;
1671   ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
1672   ui.cur_brush->ruler = ui.default_brushes[TOOL_PEN].ruler;
1673   ui.cur_brush->recognizer = ui.default_brushes[TOOL_PEN].recognizer;
1674   update_mapping_linkings(TOOL_PEN);
1675   update_tool_buttons();
1676   update_tool_menu();
1677   update_color_menu();
1678   update_cursor();
1679 }
1680
1681
1682 void
1683 on_toolsEraser_activate                (GtkMenuItem     *menuitem,
1684                                         gpointer         user_data)
1685 {
1686   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1687     if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1688       return;
1689   } else {
1690     if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1691       return;
1692   }
1693   
1694   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1695   if (ui.toolno[ui.cur_mapping] == TOOL_ERASER) return;
1696   
1697   ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1698   end_text();
1699   reset_selection();
1700   ui.toolno[ui.cur_mapping] = TOOL_ERASER;
1701   ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_ERASER]);
1702   update_mapping_linkings(TOOL_ERASER);
1703   update_tool_buttons();
1704   update_tool_menu();
1705   update_color_menu();
1706   update_cursor();
1707 }
1708
1709
1710 void
1711 on_toolsHighlighter_activate           (GtkMenuItem     *menuitem,
1712                                         gpointer         user_data)
1713 {
1714   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1715     if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1716       return;
1717   } else {
1718     if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1719       return;
1720   }
1721   
1722   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1723   if (ui.toolno[ui.cur_mapping] == TOOL_HIGHLIGHTER) return;
1724   
1725   ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1726   end_text();
1727   reset_selection();
1728   ui.toolno[ui.cur_mapping] = TOOL_HIGHLIGHTER;
1729   ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_HIGHLIGHTER]);
1730   ui.cur_brush->ruler = ui.default_brushes[TOOL_HIGHLIGHTER].ruler;
1731   ui.cur_brush->recognizer = ui.default_brushes[TOOL_HIGHLIGHTER].recognizer;
1732   update_mapping_linkings(TOOL_HIGHLIGHTER);
1733   update_tool_buttons();
1734   update_tool_menu();
1735   update_color_menu();
1736   update_cursor();
1737 }
1738
1739
1740 void
1741 on_toolsText_activate                  (GtkMenuItem     *menuitem,
1742                                         gpointer         user_data)
1743 {
1744   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1745     if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1746       return;
1747   } else {
1748     if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1749       return;
1750   }
1751   
1752   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1753   if (ui.toolno[ui.cur_mapping] == TOOL_TEXT) return;
1754   
1755   ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1756   reset_selection();
1757   ui.toolno[ui.cur_mapping] = TOOL_TEXT;
1758   ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
1759   update_mapping_linkings(-1);
1760   update_tool_buttons();
1761   update_tool_menu();
1762   update_color_menu();
1763   update_cursor();
1764 }
1765
1766
1767 void
1768 on_toolsSelectRegion_activate          (GtkMenuItem     *menuitem,
1769                                         gpointer         user_data)
1770 {
1771
1772 }
1773
1774
1775 void
1776 on_toolsSelectRectangle_activate       (GtkMenuItem     *menuitem,
1777                                         gpointer         user_data)
1778 {
1779   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1780     if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1781       return;
1782   } else {
1783     if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1784       return;
1785   }
1786   
1787   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1788   if (ui.toolno[ui.cur_mapping] == TOOL_SELECTRECT) return;
1789   
1790   ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1791   end_text();
1792   ui.toolno[ui.cur_mapping] = TOOL_SELECTRECT;
1793   update_mapping_linkings(-1);
1794   update_tool_buttons();
1795   update_tool_menu();
1796   update_color_menu();
1797   update_cursor();
1798 }
1799
1800
1801 void
1802 on_toolsVerticalSpace_activate         (GtkMenuItem     *menuitem,
1803                                         gpointer         user_data)
1804 {
1805   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1806     if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1807       return;
1808   } else {
1809     if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1810       return;
1811   }
1812   
1813   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1814   if (ui.toolno[ui.cur_mapping] == TOOL_VERTSPACE) return;
1815   
1816   ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1817   end_text();
1818   reset_selection();
1819   ui.toolno[ui.cur_mapping] = TOOL_VERTSPACE;
1820   update_mapping_linkings(-1);
1821   update_tool_buttons();
1822   update_tool_menu();
1823   update_color_menu();
1824   update_cursor();
1825 }
1826
1827
1828 void
1829 on_colorBlack_activate                 (GtkMenuItem     *menuitem,
1830                                         gpointer         user_data)
1831 {
1832   process_color_activate(menuitem, COLOR_BLACK, predef_colors_rgba[COLOR_BLACK]);
1833 }
1834
1835
1836 void
1837 on_colorBlue_activate                  (GtkMenuItem     *menuitem,
1838                                         gpointer         user_data)
1839 {
1840   process_color_activate(menuitem, COLOR_BLUE, predef_colors_rgba[COLOR_BLUE]);
1841 }
1842
1843
1844 void
1845 on_colorRed_activate                   (GtkMenuItem     *menuitem,
1846                                         gpointer         user_data)
1847 {
1848   process_color_activate(menuitem, COLOR_RED, predef_colors_rgba[COLOR_RED]);
1849 }
1850
1851
1852 void
1853 on_colorGreen_activate                 (GtkMenuItem     *menuitem,
1854                                         gpointer         user_data)
1855 {
1856   process_color_activate(menuitem, COLOR_GREEN, predef_colors_rgba[COLOR_GREEN]);
1857 }
1858
1859
1860 void
1861 on_colorGray_activate                  (GtkMenuItem     *menuitem,
1862                                         gpointer         user_data)
1863 {
1864   process_color_activate(menuitem, COLOR_GRAY, predef_colors_rgba[COLOR_GRAY]);
1865 }
1866
1867
1868 void
1869 on_colorLightBlue_activate             (GtkMenuItem     *menuitem,
1870                                         gpointer         user_data)
1871 {
1872   process_color_activate(menuitem, COLOR_LIGHTBLUE, predef_colors_rgba[COLOR_LIGHTBLUE]);
1873 }
1874
1875
1876 void
1877 on_colorLightGreen_activate            (GtkMenuItem     *menuitem,
1878                                         gpointer         user_data)
1879 {
1880   process_color_activate(menuitem, COLOR_LIGHTGREEN, predef_colors_rgba[COLOR_LIGHTGREEN]);
1881 }
1882
1883
1884 void
1885 on_colorMagenta_activate               (GtkMenuItem     *menuitem,
1886                                         gpointer         user_data)
1887 {
1888   process_color_activate(menuitem, COLOR_MAGENTA, predef_colors_rgba[COLOR_MAGENTA]);
1889 }
1890
1891
1892 void
1893 on_colorOrange_activate                (GtkMenuItem     *menuitem,
1894                                         gpointer         user_data)
1895 {
1896   process_color_activate(menuitem, COLOR_ORANGE, predef_colors_rgba[COLOR_ORANGE]);
1897 }
1898
1899
1900 void
1901 on_colorYellow_activate                (GtkMenuItem     *menuitem,
1902                                         gpointer         user_data)
1903 {
1904   process_color_activate(menuitem, COLOR_YELLOW, predef_colors_rgba[COLOR_YELLOW]);
1905 }
1906
1907
1908 void
1909 on_colorWhite_activate                 (GtkMenuItem     *menuitem,
1910                                         gpointer         user_data)
1911 {
1912   process_color_activate(menuitem, COLOR_WHITE, predef_colors_rgba[COLOR_WHITE]);
1913 }
1914
1915
1916 void
1917 on_colorOther_activate                 (GtkMenuItem     *menuitem,
1918                                         gpointer         user_data)
1919 {
1920   gtk_button_clicked(GTK_BUTTON(GET_COMPONENT("buttonColorChooser")));
1921 }
1922
1923
1924 void
1925 on_penthicknessVeryFine_activate       (GtkMenuItem     *menuitem,
1926                                         gpointer         user_data)
1927 {
1928   process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_VERYFINE);
1929 }
1930
1931
1932 void
1933 on_penthicknessFine_activate           (GtkMenuItem     *menuitem,
1934                                         gpointer         user_data)
1935 {
1936   process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_FINE);
1937 }
1938
1939
1940 void
1941 on_penthicknessMedium_activate         (GtkMenuItem     *menuitem,
1942                                         gpointer         user_data)
1943 {
1944   process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_MEDIUM);
1945 }
1946
1947
1948 void
1949 on_penthicknessThick_activate          (GtkMenuItem     *menuitem,
1950                                         gpointer         user_data)
1951 {
1952   process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_THICK);
1953 }
1954
1955
1956 void
1957 on_penthicknessVeryThick_activate      (GtkMenuItem     *menuitem,
1958                                         gpointer         user_data)
1959 {
1960   process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_VERYTHICK);
1961 }
1962
1963
1964 void
1965 on_eraserFine_activate                 (GtkMenuItem     *menuitem,
1966                                         gpointer         user_data)
1967 {
1968   process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_FINE);
1969 }
1970
1971
1972 void
1973 on_eraserMedium_activate               (GtkMenuItem     *menuitem,
1974                                         gpointer         user_data)
1975 {
1976   process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_MEDIUM);
1977 }
1978
1979
1980 void
1981 on_eraserThick_activate                (GtkMenuItem     *menuitem,
1982                                         gpointer         user_data)
1983 {
1984   process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_THICK);
1985 }
1986
1987
1988 void
1989 on_eraserStandard_activate             (GtkMenuItem     *menuitem,
1990                                         gpointer         user_data)
1991 {
1992   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
1993   end_text();
1994   ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_STANDARD;
1995   update_mapping_linkings(TOOL_ERASER);
1996 }
1997
1998
1999 void
2000 on_eraserWhiteout_activate             (GtkMenuItem     *menuitem,
2001                                         gpointer         user_data)
2002 {
2003   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
2004   end_text();
2005   ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_WHITEOUT;
2006   update_mapping_linkings(TOOL_ERASER);
2007 }
2008
2009
2010 void
2011 on_eraserDeleteStrokes_activate        (GtkMenuItem     *menuitem,
2012                                         gpointer         user_data)
2013 {
2014   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
2015   end_text();
2016   ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_STROKES;
2017   update_mapping_linkings(TOOL_ERASER);
2018 }
2019
2020
2021 void
2022 on_highlighterFine_activate            (GtkMenuItem     *menuitem,
2023                                         gpointer         user_data)
2024 {
2025   process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_FINE);
2026 }
2027
2028
2029 void
2030 on_highlighterMedium_activate          (GtkMenuItem     *menuitem,
2031                                         gpointer         user_data)
2032 {
2033   process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_MEDIUM);
2034 }
2035
2036
2037 void
2038 on_highlighterThick_activate           (GtkMenuItem     *menuitem,
2039                                         gpointer         user_data)
2040 {
2041   process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_THICK);
2042 }
2043
2044
2045 void
2046 on_toolsTextFont_activate              (GtkMenuItem     *menuitem,
2047                                         gpointer         user_data)
2048 {
2049   GtkWidget *dialog;
2050   gchar *str;
2051   
2052   dialog = gtk_font_selection_dialog_new(_("Select Font"));
2053   str = make_cur_font_name();
2054   gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dialog), str);
2055   g_free(str);
2056   if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
2057     gtk_widget_destroy(dialog);
2058     return;
2059   }
2060   str = gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(dialog));
2061   gtk_widget_destroy(dialog);
2062   process_font_sel(str);
2063 }    
2064
2065 void
2066 on_toolsDefaultPen_activate            (GtkMenuItem     *menuitem,
2067                                         gpointer         user_data)
2068 {
2069   switch_mapping(0);
2070   end_text();
2071   reset_selection();
2072   g_memmove(&(ui.brushes[0][TOOL_PEN]), ui.default_brushes+TOOL_PEN, sizeof(struct Brush));
2073   ui.toolno[0] = TOOL_PEN;
2074   ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
2075   update_mapping_linkings(TOOL_PEN);
2076   update_tool_buttons();
2077   update_tool_menu();
2078   update_pen_props_menu();
2079   update_color_menu();
2080   update_cursor();
2081 }
2082
2083
2084 void
2085 on_toolsDefaultEraser_activate         (GtkMenuItem     *menuitem,
2086                                         gpointer         user_data)
2087 {
2088   switch_mapping(0);
2089   end_text();
2090   reset_selection();
2091   g_memmove(&(ui.brushes[0][TOOL_ERASER]), ui.default_brushes+TOOL_ERASER, sizeof(struct Brush));
2092   ui.toolno[0] = TOOL_ERASER;
2093   ui.cur_brush = &(ui.brushes[0][TOOL_ERASER]);
2094   update_mapping_linkings(TOOL_ERASER);
2095   update_tool_buttons();
2096   update_tool_menu();
2097   update_eraser_props_menu();
2098   update_color_menu();
2099   update_cursor();
2100 }
2101
2102
2103 void
2104 on_toolsDefaultHighlighter_activate    (GtkMenuItem     *menuitem,
2105                                         gpointer         user_data)
2106 {
2107   switch_mapping(0);
2108   end_text();
2109   reset_selection();
2110   g_memmove(&(ui.brushes[0][TOOL_HIGHLIGHTER]), ui.default_brushes+TOOL_HIGHLIGHTER, sizeof(struct Brush));
2111   ui.toolno[0] = TOOL_HIGHLIGHTER;
2112   ui.cur_brush = &(ui.brushes[0][TOOL_HIGHLIGHTER]);
2113   update_mapping_linkings(TOOL_HIGHLIGHTER);
2114   update_tool_buttons();
2115   update_tool_menu();
2116   update_highlighter_props_menu();
2117   update_color_menu();
2118   update_cursor();
2119 }
2120
2121 void
2122 on_toolsDefaultText_activate           (GtkMenuItem     *menuitem,
2123                                         gpointer         user_data)
2124 {
2125   switch_mapping(0);
2126   if (ui.toolno[0]!=TOOL_TEXT) end_text();
2127   reset_selection();
2128   ui.toolno[0] = TOOL_TEXT;
2129   ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
2130   ui.cur_brush->color_no = ui.default_brushes[TOOL_PEN].color_no;
2131   ui.cur_brush->color_rgba = ui.default_brushes[TOOL_PEN].color_rgba;
2132   g_free(ui.font_name);
2133   ui.font_name = g_strdup(ui.default_font_name);
2134   ui.font_size = ui.default_font_size;
2135   if (ui.cur_item_type == ITEM_TEXT) {
2136     refont_text_item(ui.cur_item, ui.font_name, ui.font_size);
2137   }
2138   update_font_button();
2139   update_mapping_linkings(-1);
2140   update_tool_buttons();
2141   update_tool_menu();
2142   update_color_menu();
2143   update_cursor();
2144 }
2145
2146
2147 void
2148 on_toolsSetAsDefault_activate          (GtkMenuItem     *menuitem,
2149                                         gpointer         user_data)
2150 {
2151   struct Item *it;
2152   
2153   if (ui.cur_mapping!=0 && !ui.button_switch_mapping) return;
2154   if (ui.toolno[ui.cur_mapping] < NUM_STROKE_TOOLS)
2155     g_memmove(ui.default_brushes+ui.toolno[ui.cur_mapping], 
2156               &(ui.brushes[ui.cur_mapping][ui.toolno[ui.cur_mapping]]), sizeof(struct Brush));
2157   if (ui.toolno[ui.cur_mapping] == TOOL_TEXT) {
2158     if (ui.cur_item_type == ITEM_TEXT) {
2159       g_free(ui.font_name);
2160       ui.font_name = g_strdup(ui.cur_item->font_name);
2161       ui.font_size = ui.cur_item->font_size;
2162     }
2163     else if (ui.selection!=NULL && ui.selection->items!=NULL &&
2164              ui.selection->items->next==NULL &&
2165              (it=(struct Item*)ui.selection->items->data)->type == ITEM_TEXT) {
2166       g_free(ui.font_name);
2167       ui.font_name = g_strdup(it->font_name);
2168       ui.font_size = it->font_size;
2169     }
2170     g_free(ui.default_font_name);
2171     ui.default_font_name = g_strdup(ui.font_name);
2172     ui.default_font_size = ui.font_size;
2173   }
2174   end_text();
2175 }
2176
2177
2178 void
2179 on_toolsRuler_activate                 (GtkMenuItem     *menuitem,
2180                                         gpointer         user_data)
2181 {
2182   gboolean active, current;
2183   
2184   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
2185     active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2186   else
2187     active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
2188
2189   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2190   current = (ui.toolno[ui.cur_mapping] == TOOL_PEN || ui.toolno[ui.cur_mapping] == TOOL_HIGHLIGHTER) && ui.cur_brush->ruler;
2191   if (active == current) return;
2192
2193   ui.cur_mapping = 0;  
2194   end_text();
2195   if (ui.toolno[ui.cur_mapping]!=TOOL_PEN && ui.toolno[ui.cur_mapping]!=TOOL_HIGHLIGHTER) {
2196     reset_selection();
2197     ui.toolno[ui.cur_mapping] = TOOL_PEN;
2198     ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
2199     update_color_menu();
2200     update_tool_buttons();
2201     update_tool_menu();
2202     update_cursor();
2203   }
2204   
2205   ui.cur_brush->ruler = active;
2206   if (active) ui.cur_brush->recognizer = FALSE;
2207   update_mapping_linkings(ui.toolno[ui.cur_mapping]);
2208   update_ruler_indicator();
2209 }
2210
2211
2212 void
2213 on_toolsReco_activate                  (GtkMenuItem *menuitem,
2214                                         gpointer         user_data)
2215 {
2216   gboolean active, current;
2217   
2218   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
2219     active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2220   else
2221     active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
2222
2223   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2224   current = (ui.toolno[ui.cur_mapping] == TOOL_PEN || ui.toolno[ui.cur_mapping] == TOOL_HIGHLIGHTER) && ui.cur_brush->recognizer;
2225   if (active == current) return;
2226   
2227   ui.cur_mapping = 0;
2228   end_text();
2229   if (ui.toolno[ui.cur_mapping]!=TOOL_PEN && ui.toolno[ui.cur_mapping]!=TOOL_HIGHLIGHTER) {
2230     reset_selection();
2231     ui.toolno[ui.cur_mapping] = TOOL_PEN;
2232     ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
2233     update_color_menu();
2234     update_tool_buttons();
2235     update_tool_menu();
2236     update_cursor();
2237   }
2238   
2239   ui.cur_brush->recognizer = active;
2240   if (active) {
2241     ui.cur_brush->ruler = FALSE;
2242     reset_recognizer();
2243   }
2244   update_mapping_linkings(ui.toolno[ui.cur_mapping]);
2245   update_ruler_indicator();
2246 }
2247
2248
2249 void
2250 on_optionsSavePreferences_activate     (GtkMenuItem     *menuitem,
2251                                         gpointer         user_data)
2252 {
2253   end_text();
2254   save_config_to_file();
2255 }
2256
2257
2258 void
2259 on_helpIndex_activate                  (GtkMenuItem     *menuitem,
2260                                         gpointer         user_data)
2261 {
2262
2263 }
2264
2265
2266 void
2267 on_helpAbout_activate                  (GtkMenuItem     *menuitem,
2268                                         gpointer         user_data)
2269 {
2270   GtkWidget *aboutDialog;
2271   GtkLabel *labelTitle;
2272   
2273   end_text();
2274   aboutDialog = create_aboutDialog ();
2275   labelTitle = GTK_LABEL(g_object_get_data(G_OBJECT(aboutDialog), "labelTitle"));
2276   gtk_label_set_markup(labelTitle, 
2277     "<span size=\"xx-large\" weight=\"bold\">Xournal " VERSION_STRING "</span>");
2278   gtk_dialog_run (GTK_DIALOG(aboutDialog));
2279   gtk_widget_destroy(aboutDialog);
2280 }
2281
2282
2283 void
2284 on_buttonToolDefault_clicked           (GtkToolButton   *toolbutton,
2285                                         gpointer         user_data)
2286 {
2287   if (ui.toolno[0]==TOOL_TEXT) {
2288     on_toolsDefaultText_activate(NULL, NULL);
2289     return;
2290   }
2291   end_text();
2292   switch_mapping(0);
2293   if (ui.toolno[0] < NUM_STROKE_TOOLS) {
2294     g_memmove(&(ui.brushes[0][ui.toolno[0]]), ui.default_brushes+ui.toolno[0], sizeof(struct Brush));
2295     update_mapping_linkings(ui.toolno[0]);
2296     update_thickness_buttons();
2297     update_color_buttons();
2298     update_color_menu();
2299     if (ui.toolno[0] == TOOL_PEN) update_pen_props_menu();
2300     if (ui.toolno[0] == TOOL_ERASER) update_eraser_props_menu();
2301     if (ui.toolno[0] == TOOL_HIGHLIGHTER) update_highlighter_props_menu();
2302     update_cursor();
2303   }
2304 }
2305
2306
2307 void
2308 on_buttonFine_clicked                  (GtkToolButton   *toolbutton,
2309                                         gpointer         user_data)
2310 {
2311   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2312   process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[ui.cur_mapping], THICKNESS_FINE);
2313 }
2314
2315
2316 void
2317 on_buttonMedium_clicked                (GtkToolButton   *toolbutton,
2318                                         gpointer         user_data)
2319 {
2320   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2321   process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[ui.cur_mapping], THICKNESS_MEDIUM);
2322 }
2323
2324
2325 void
2326 on_buttonThick_clicked                 (GtkToolButton   *toolbutton,
2327                                         gpointer         user_data)
2328 {
2329   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2330   process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[ui.cur_mapping], THICKNESS_THICK);
2331 }
2332
2333
2334 gboolean
2335 on_canvas_button_press_event           (GtkWidget       *widget,
2336                                         GdkEventButton  *event,
2337                                         gpointer         user_data)
2338 {
2339   double pt[2];
2340   gboolean page_change;
2341   struct Page *tmppage;
2342   GtkWidget *dialog;
2343   int mapping;
2344   gboolean is_core;
2345   struct Item *item;
2346   GdkEvent scroll_event;
2347
2348 #ifdef INPUT_DEBUG
2349   printf("DEBUG: ButtonPress (%s) (x,y)=(%.2f,%.2f), button %d, modifier %x\n", 
2350     event->device->name, event->x, event->y, event->button, event->state);
2351 #endif
2352
2353   // abort any page changes pending in the spin button, and take the focus
2354   gtk_spin_button_set_value(GTK_SPIN_BUTTON(GET_COMPONENT("spinPageNo")), ui.pageno+1);
2355   reset_focus();
2356     
2357   is_core = (event->device == gdk_device_get_core_pointer());
2358   if (!ui.use_xinput && !is_core) return FALSE;
2359   if (ui.use_xinput && is_core && ui.discard_corepointer) return FALSE;
2360   if (event->type != GDK_BUTTON_PRESS) return FALSE; 
2361     // double-clicks may have broken axes member (free'd) due to a bug in GDK
2362
2363   if (event->button > 3) { // scroll wheel events! don't paint...
2364     if (ui.use_xinput && !gtk_check_version(2, 17, 0) && event->button <= 7) {
2365       /* with GTK+ 2.17 and later, the entire widget hierarchy is xinput-aware,
2366          so the core button event gets discarded and the scroll event never 
2367          gets processed by the main window. This is arguably a GTK+ bug.
2368          We work around it. */
2369       scroll_event.scroll.type = GDK_SCROLL;
2370       scroll_event.scroll.window = event->window;
2371       scroll_event.scroll.send_event = event->send_event;
2372       scroll_event.scroll.time = event->time;
2373       scroll_event.scroll.x = event->x;
2374       scroll_event.scroll.y = event->y;
2375       scroll_event.scroll.state = event->state;
2376       scroll_event.scroll.device = event->device;
2377       scroll_event.scroll.x_root = event->x_root;
2378       scroll_event.scroll.y_root = event->y_root;
2379       if (event->button == 4) scroll_event.scroll.direction = GDK_SCROLL_UP;
2380       else if (event->button == 5) scroll_event.scroll.direction = GDK_SCROLL_DOWN;
2381       else if (event->button == 6) scroll_event.scroll.direction = GDK_SCROLL_LEFT;
2382       else scroll_event.scroll.direction = GDK_SCROLL_RIGHT;
2383       gtk_widget_event(GET_COMPONENT("scrolledwindowMain"), &scroll_event);
2384     }
2385     return FALSE;
2386   }
2387   if ((event->state & (GDK_CONTROL_MASK|GDK_MOD1_MASK)) != 0) return FALSE;
2388     // no control-clicking or alt-clicking
2389   if (!is_core) gdk_device_get_state(event->device, event->window, event->axes, NULL);
2390     // synaptics touchpads send bogus axis values with ButtonDown
2391   if (!is_core)
2392     fix_xinput_coords((GdkEvent *)event);
2393
2394   if (!finite_sized(event->x) || !finite_sized(event->y)) return FALSE; // Xorg 7.3 bug
2395
2396   if (ui.cur_item_type == ITEM_TEXT) {
2397     if (!is_event_within_textview(event)) end_text();
2398     else return FALSE;
2399   }
2400   if (ui.cur_item_type == ITEM_STROKE && ui.is_corestroke && !is_core &&
2401       ui.cur_path.num_points == 1) { 
2402       // Xorg 7.3+ sent core event before XInput event: fix initial point 
2403     ui.is_corestroke = FALSE;
2404     get_pointer_coords((GdkEvent *)event, ui.cur_path.coords);
2405   }
2406   if (ui.cur_item_type != ITEM_NONE) return FALSE; // we're already doing something
2407
2408   // if button_switch_mapping enabled, button 2 or 3 clicks only switch mapping
2409   if (ui.button_switch_mapping && event->button > 1) {
2410     ui.which_unswitch_button = event->button;
2411     switch_mapping(event->button-1);
2412     return FALSE;
2413   }
2414
2415   ui.is_corestroke = is_core;
2416   ui.stroke_device = event->device;
2417
2418   if (ui.use_erasertip && event->device->source == GDK_SOURCE_ERASER)
2419     mapping = NUM_BUTTONS;
2420   else if (ui.button_switch_mapping) {
2421     mapping = ui.cur_mapping;
2422     if (!mapping && (event->state & GDK_BUTTON2_MASK)) mapping = 1;
2423     if (!mapping && (event->state & GDK_BUTTON3_MASK)) mapping = 2;
2424   }
2425   else mapping = event->button-1;
2426
2427   // check whether we're in a page
2428   page_change = FALSE;
2429   tmppage = ui.cur_page;
2430   get_pointer_coords((GdkEvent *)event, pt);
2431   while (ui.view_continuous && (pt[1] < - VIEW_CONTINUOUS_SKIP)) {
2432     if (ui.pageno == 0) break;
2433     page_change = TRUE;
2434     ui.pageno--;
2435     tmppage = g_list_nth_data(journal.pages, ui.pageno);
2436     pt[1] += tmppage->height + VIEW_CONTINUOUS_SKIP;
2437   }
2438   while (ui.view_continuous && (pt[1] > tmppage->height + VIEW_CONTINUOUS_SKIP)) {
2439     if (ui.pageno == journal.npages-1) break;
2440     pt[1] -= tmppage->height + VIEW_CONTINUOUS_SKIP;
2441     page_change = TRUE;
2442     ui.pageno++;
2443     tmppage = g_list_nth_data(journal.pages, ui.pageno);
2444   }
2445   if (page_change) do_switch_page(ui.pageno, FALSE, FALSE);
2446   
2447   // can't paint on the background...
2448
2449   if (ui.cur_layer == NULL) {
2450     /* warn */
2451     dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL,
2452       GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("Drawing is not allowed on the "
2453       "background layer.\n Switching to Layer 1."));
2454     gtk_dialog_run(GTK_DIALOG(dialog));
2455     gtk_widget_destroy(dialog);
2456     on_viewShowLayer_activate(NULL, NULL);
2457     return FALSE;
2458   }
2459
2460   // switch mappings if needed
2461   
2462   ui.which_mouse_button = event->button;
2463   switch_mapping(mapping);
2464 #ifdef WIN32
2465   update_cursor();
2466 #endif
2467
2468   // in text tool, clicking in a text area edits it
2469   if (ui.toolno[mapping] == TOOL_TEXT) {
2470     item = click_is_in_text(ui.cur_layer, pt[0], pt[1]);
2471     if (item!=NULL) { 
2472       reset_selection();
2473       start_text((GdkEvent *)event, item);
2474       return FALSE;
2475     }
2476   }
2477
2478   // if this can be a selection move or resize, then it takes precedence over anything else  
2479   if (start_resizesel((GdkEvent *)event)) return FALSE;
2480   if (start_movesel((GdkEvent *)event)) return FALSE;
2481   
2482   if (ui.toolno[mapping] != TOOL_SELECTREGION && ui.toolno[mapping] != TOOL_SELECTRECT)
2483     reset_selection();
2484
2485   // process the event
2486   
2487   if (ui.toolno[mapping] == TOOL_HAND) {
2488     ui.cur_item_type = ITEM_HAND;
2489     get_pointer_coords((GdkEvent *)event, ui.hand_refpt);
2490     ui.hand_refpt[0] += ui.cur_page->hoffset;
2491     ui.hand_refpt[1] += ui.cur_page->voffset;
2492   } 
2493   else if (ui.toolno[mapping] == TOOL_PEN || ui.toolno[mapping] == TOOL_HIGHLIGHTER ||
2494         (ui.toolno[mapping] == TOOL_ERASER && ui.cur_brush->tool_options == TOOLOPT_ERASER_WHITEOUT)) {
2495     create_new_stroke((GdkEvent *)event);
2496   } 
2497   else if (ui.toolno[mapping] == TOOL_ERASER) {
2498     ui.cur_item_type = ITEM_ERASURE;
2499     do_eraser((GdkEvent *)event, ui.cur_brush->thickness/2,
2500                ui.cur_brush->tool_options == TOOLOPT_ERASER_STROKES);
2501   }
2502   else if (ui.toolno[mapping] == TOOL_SELECTRECT) {
2503     start_selectrect((GdkEvent *)event);
2504   }
2505   else if (ui.toolno[mapping] == TOOL_VERTSPACE) {
2506     start_vertspace((GdkEvent *)event);
2507   }
2508   else if (ui.toolno[mapping] == TOOL_TEXT) {
2509     start_text((GdkEvent *)event, NULL);
2510   }
2511   return FALSE;
2512 }
2513
2514
2515 gboolean
2516 on_canvas_button_release_event         (GtkWidget       *widget,
2517                                         GdkEventButton  *event,
2518                                         gpointer         user_data)
2519 {
2520   gboolean is_core;
2521   
2522 #ifdef INPUT_DEBUG
2523   printf("DEBUG: ButtonRelease (%s) (x,y)=(%.2f,%.2f), button %d, modifier %x\n", 
2524       event->device->name, event->x, event->y, event->button, event->state);
2525 #endif
2526
2527   is_core = (event->device == gdk_device_get_core_pointer());
2528   if (!ui.use_xinput && !is_core) return FALSE;
2529   if (ui.use_xinput && is_core && !ui.is_corestroke) return FALSE;
2530   if (!is_core) fix_xinput_coords((GdkEvent *)event);
2531
2532   if (event->button != ui.which_mouse_button && 
2533       event->button != ui.which_unswitch_button)
2534     return FALSE;
2535
2536   if (ui.cur_item_type == ITEM_STROKE) {
2537     finalize_stroke();
2538     if (ui.cur_brush->recognizer) recognize_patterns();
2539   }
2540   else if (ui.cur_item_type == ITEM_ERASURE) {
2541     finalize_erasure();
2542   }
2543   else if (ui.cur_item_type == ITEM_SELECTRECT) {
2544     finalize_selectrect();
2545   }
2546   else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2547     finalize_movesel();
2548   }
2549   else if (ui.cur_item_type == ITEM_RESIZESEL) {
2550     finalize_resizesel();
2551   }
2552   else if (ui.cur_item_type == ITEM_HAND) {
2553     ui.cur_item_type = ITEM_NONE;
2554   }
2555   
2556   if (!ui.which_unswitch_button || event->button == ui.which_unswitch_button)
2557     switch_mapping(0); // will reset ui.which_unswitch_button
2558
2559   return FALSE;
2560 }
2561
2562
2563 gboolean
2564 on_canvas_enter_notify_event           (GtkWidget       *widget,
2565                                         GdkEventCrossing *event,
2566                                         gpointer         user_data)
2567 {
2568   GList *dev_list;
2569   GdkDevice *dev;
2570
2571 #ifdef INPUT_DEBUG
2572   printf("DEBUG: enter notify\n");
2573 #endif
2574     /* re-enable input devices after they've been emergency-disabled
2575        by leave_notify */
2576   if (!gtk_check_version(2, 17, 0)) {
2577     gdk_flush();
2578     gdk_error_trap_push();
2579     for (dev_list = gdk_devices_list(); dev_list != NULL; dev_list = dev_list->next) {
2580       dev = GDK_DEVICE(dev_list->data);
2581       gdk_device_set_mode(dev, GDK_MODE_SCREEN);
2582     }
2583     ui.is_corestroke = ui.saved_is_corestroke;
2584     gdk_flush();
2585     gdk_error_trap_pop();
2586   }
2587   return FALSE;
2588 }
2589
2590 gboolean
2591 on_canvas_leave_notify_event           (GtkWidget       *widget,
2592                                         GdkEventCrossing *event,
2593                                         gpointer         user_data)
2594 {
2595   GList *dev_list;
2596   GdkDevice *dev;
2597
2598 #ifdef INPUT_DEBUG
2599   printf("DEBUG: leave notify (mode=%d, details=%d)\n", event->mode, event->detail);
2600 #endif
2601     /* emergency disable XInput to avoid segfaults (GTK+ 2.17) or 
2602        interface non-responsiveness (GTK+ 2.18) */
2603   if (!gtk_check_version(2, 17, 0)) {
2604     gdk_flush();
2605     gdk_error_trap_push();
2606     for (dev_list = gdk_devices_list(); dev_list != NULL; dev_list = dev_list->next) {
2607       dev = GDK_DEVICE(dev_list->data);
2608       gdk_device_set_mode(dev, GDK_MODE_DISABLED);
2609     }
2610     ui.saved_is_corestroke = ui.is_corestroke;
2611     ui.is_corestroke = TRUE;
2612     gdk_flush();
2613     gdk_error_trap_pop();
2614   }
2615   return FALSE;
2616 }
2617
2618
2619 gboolean
2620 on_canvas_expose_event                 (GtkWidget       *widget,
2621                                         GdkEventExpose  *event,
2622                                         gpointer         user_data)
2623 {
2624   if (ui.view_continuous && ui.progressive_bg) rescale_bg_pixmaps();
2625   return FALSE;
2626 }
2627
2628
2629 gboolean
2630 on_canvas_key_press_event              (GtkWidget       *widget,
2631                                         GdkEventKey     *event,
2632                                         gpointer         user_data)
2633 {
2634   GtkAdjustment *adj;
2635   gint pgheight;
2636
2637   // Esc leaves text edition, or leaves fullscreen mode
2638   if (event->keyval == GDK_Escape) {
2639     if (ui.cur_item_type == ITEM_TEXT) { 
2640       end_text(); 
2641       return TRUE;
2642     }
2643     else if (ui.fullscreen) {
2644       do_fullscreen(FALSE);
2645       return TRUE;
2646     }
2647     else return FALSE;
2648   }
2649   
2650   /* In single page mode, switch pages with PgUp/PgDn (or Up/Dn) 
2651      when there's nowhere else to go. */
2652   pgheight = GTK_WIDGET(canvas)->allocation.height;
2653   adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(GET_COMPONENT("scrolledwindowMain")));
2654
2655   if (event->keyval == GDK_Page_Down || event->keyval == GDK_Down) {
2656     if (!ui.view_continuous && 
2657          (0.96 * ui.zoom * ui.cur_page->height < pgheight ||
2658           adj->value == adj->upper-pgheight)) 
2659     {
2660       end_text();
2661       if (ui.pageno < journal.npages-1)
2662         do_switch_page(ui.pageno+1, TRUE, FALSE);
2663       return TRUE;
2664     }
2665     if (adj->value == adj->upper-pgheight) return TRUE; // don't send focus away
2666   }
2667
2668   if (event->keyval == GDK_Page_Up || event->keyval == GDK_Up) {
2669     if (!ui.view_continuous && 
2670          (0.96 * ui.zoom * ui.cur_page->height < pgheight ||
2671           adj->value == adj->lower))
2672     {
2673       end_text();
2674       if (ui.pageno != 0) {
2675         do_switch_page(ui.pageno-1, TRUE, FALSE);
2676         gtk_adjustment_set_value(adj, adj->upper-pgheight);
2677       }
2678       return TRUE;
2679     }
2680     if (adj->value == adj->lower) return TRUE; // don't send focus away
2681   }
2682
2683   return FALSE;
2684 }
2685
2686
2687 gboolean
2688 on_canvas_motion_notify_event          (GtkWidget       *widget,
2689                                         GdkEventMotion  *event,
2690                                         gpointer         user_data)
2691 {
2692   gboolean looks_wrong, is_core;
2693   double pt[2];
2694   GdkModifierType mask;
2695
2696   /* we don't care about this event unless some operation is in progress;
2697      or if there's a selection (then we might want to change the mouse
2698      cursor to indicate the possibility of resizing) */  
2699   if (ui.cur_item_type == ITEM_NONE && ui.selection==NULL) return FALSE;
2700   if (ui.cur_item_type == ITEM_TEXT) return FALSE;
2701
2702   is_core = (event->device == gdk_device_get_core_pointer());
2703   if (!ui.use_xinput && !is_core) return FALSE;
2704   if (!is_core) fix_xinput_coords((GdkEvent *)event);
2705   if (!finite_sized(event->x) || !finite_sized(event->y)) return FALSE; // Xorg 7.3 bug
2706
2707   if (ui.selection!=NULL && ui.cur_item_type == ITEM_NONE) {
2708     get_pointer_coords((GdkEvent *)event, pt);
2709     update_cursor_for_resize(pt);
2710     return FALSE;
2711   }
2712
2713   if (ui.use_xinput && is_core && !ui.is_corestroke) return FALSE;
2714   if (!is_core) ui.is_corestroke = FALSE;
2715
2716 #ifdef INPUT_DEBUG
2717   printf("DEBUG: MotionNotify (%s) (x,y)=(%.2f,%.2f), modifier %x\n", 
2718     is_core?"core":"xinput", event->x, event->y, event->state);
2719 #endif
2720   
2721   looks_wrong = !(event->state & (1<<(7+ui.which_mouse_button)));
2722   if (looks_wrong) {
2723     gdk_device_get_state(ui.stroke_device, event->window, NULL, &mask);
2724     looks_wrong = !(mask & (1<<(7+ui.which_mouse_button)));
2725   }
2726   
2727   if (looks_wrong) { /* mouse button shouldn't be up... give up */
2728     if (ui.cur_item_type == ITEM_STROKE) {
2729       finalize_stroke();
2730       if (ui.cur_brush->recognizer) recognize_patterns();
2731     }
2732     else if (ui.cur_item_type == ITEM_ERASURE) {
2733       finalize_erasure();
2734     }
2735     else if (ui.cur_item_type == ITEM_SELECTRECT) {
2736       finalize_selectrect();
2737     }
2738     else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2739       finalize_movesel();
2740     }
2741     else if (ui.cur_item_type == ITEM_RESIZESEL) {
2742       finalize_resizesel();
2743     }
2744     else if (ui.cur_item_type == ITEM_HAND) {
2745       ui.cur_item_type = ITEM_NONE;
2746     }
2747     switch_mapping(0);
2748     return FALSE;
2749   }
2750   
2751   if (ui.cur_item_type == ITEM_STROKE) {
2752     continue_stroke((GdkEvent *)event);
2753   }
2754   else if (ui.cur_item_type == ITEM_ERASURE) {
2755     do_eraser((GdkEvent *)event, ui.cur_brush->thickness/2,
2756                ui.cur_brush->tool_options == TOOLOPT_ERASER_STROKES);
2757   }
2758   else if (ui.cur_item_type == ITEM_SELECTRECT) {
2759     get_pointer_coords((GdkEvent *)event, pt);
2760     ui.selection->bbox.right = pt[0];
2761     ui.selection->bbox.bottom = pt[1];
2762     gnome_canvas_item_set(ui.selection->canvas_item,
2763                                "x2", pt[0], "y2", pt[1], NULL);
2764   }
2765   else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2766     continue_movesel((GdkEvent *)event);
2767   }
2768   else if (ui.cur_item_type == ITEM_RESIZESEL) {
2769     continue_resizesel((GdkEvent *)event);
2770   }
2771   else if (ui.cur_item_type == ITEM_HAND) {
2772     do_hand((GdkEvent *)event);
2773   }
2774   
2775   return FALSE;
2776 }
2777
2778 void
2779 on_comboLayer_changed                  (GtkComboBox     *combobox,
2780                                         gpointer         user_data)
2781 {
2782   int val;
2783
2784   if (ui.in_update_page_stuff) return; // avoid a bad retroaction
2785
2786   end_text();
2787
2788   val = gtk_combo_box_get_active(combobox);
2789   if (val == -1) return;
2790   val = ui.cur_page->nlayers-1-val;
2791   if (val == ui.layerno) return;
2792
2793   reset_selection();
2794   while (val>ui.layerno) {
2795     ui.layerno++;
2796     ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
2797     gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group));
2798   }
2799   while (val<ui.layerno) {
2800     gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group));
2801     ui.layerno--;
2802     if (ui.layerno<0) ui.cur_layer = NULL;
2803     else ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
2804   }
2805   update_page_stuff();
2806 }
2807
2808
2809 gboolean
2810 on_winMain_delete_event                (GtkWidget       *widget,
2811                                         GdkEvent        *event,
2812                                         gpointer         user_data)
2813 {
2814   end_text();
2815   if (ok_to_close()) gtk_main_quit();
2816   return TRUE;
2817 }
2818
2819
2820 void
2821 on_optionsUseXInput_activate           (GtkMenuItem     *menuitem,
2822                                         gpointer         user_data)
2823 {
2824   end_text();
2825   ui.allow_xinput = ui.use_xinput =
2826     gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2827
2828 /* HOW THINGS USED TO BE:
2829
2830    We'd like on_canvas_... to get BOTH core and xinput events. Up to
2831    GTK+ 2.16 this is achieved by making only the canvas's parent 
2832    GdkWindow xinput-aware, rather than the entire hierarchy.
2833    Otherwise, the proximity detection code in GDK is broken and 
2834    we'll lose core events.
2835    
2836    Up to GTK+ 2.10, gtk_widget_set_extension_events() only sets
2837    extension events for the widget's main window itself; in GTK+ 2.11
2838    also traverses GDK child windows that belong to the widget
2839    and sets their extension events too. We want to avoid that.
2840    So we use gdk_input_set_extension_events() directly on the canvas.
2841
2842    As much as possible, we'd like to keep doing this, though GTK+ 2.17
2843    is making our life harder (crasher bugs require us to disable XInput
2844    while editing text or using the layers combo box, but disabling
2845    XInput while in a XInput-aware window causes the interface to become
2846    non-responsive). 
2847 */
2848
2849 #ifndef WIN32
2850   if (!gtk_check_version(2, 17, 0)) {
2851 #endif
2852     /* GTK+ 2.17 and later: everybody shares a single native window,
2853        so we'll never get any core events, and we might as well set 
2854        extension events the way we're supposed to. Doing so helps solve 
2855        crasher bugs in 2.17, and prevents us from losing two-button
2856        events in 2.18 */
2857     gtk_widget_set_extension_events(GTK_WIDGET (canvas), 
2858        ui.use_xinput?GDK_EXTENSION_EVENTS_ALL:GDK_EXTENSION_EVENTS_NONE);
2859 #ifndef WIN32
2860   } else {
2861 #endif
2862     /* GTK+ 2.16 and earlier: we only activate extension events on the
2863        canvas's parent GdkWindow. This allows us to keep receiving core
2864        events. */
2865     gdk_input_set_extension_events(GTK_WIDGET(canvas)->window, 
2866       GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK,
2867       ui.use_xinput?GDK_EXTENSION_EVENTS_ALL:GDK_EXTENSION_EVENTS_NONE);
2868 #ifndef WIN32
2869   }
2870 #endif
2871   
2872   update_mappings_menu();
2873 }
2874
2875 void
2876 on_vscroll_changed                     (GtkAdjustment   *adjustment,
2877                                         gpointer         user_data)
2878 {
2879   gboolean need_update;
2880   double viewport_top, viewport_bottom;
2881   struct Page *tmppage;
2882   
2883   if (!ui.view_continuous) return;
2884   
2885   if (ui.progressive_bg) rescale_bg_pixmaps();
2886   need_update = FALSE;
2887   viewport_top = adjustment->value / ui.zoom;
2888   viewport_bottom = (adjustment->value + adjustment->page_size) / ui.zoom;
2889   tmppage = ui.cur_page;
2890   while (viewport_top > tmppage->voffset + tmppage->height) {
2891     if (ui.pageno == journal.npages-1) break;
2892     need_update = TRUE;
2893     ui.pageno++;
2894     tmppage = g_list_nth_data(journal.pages, ui.pageno);
2895   }
2896   while (viewport_bottom < tmppage->voffset) {
2897     if (ui.pageno == 0) break;
2898     need_update = TRUE;
2899     ui.pageno--;
2900     tmppage = g_list_nth_data(journal.pages, ui.pageno);
2901   }
2902   if (need_update) {
2903     end_text();
2904     do_switch_page(ui.pageno, FALSE, FALSE);
2905   }
2906   return;
2907 }
2908
2909 void
2910 on_spinPageNo_value_changed            (GtkSpinButton   *spinbutton,
2911                                         gpointer         user_data)
2912 {
2913   int val;
2914
2915   if (ui.in_update_page_stuff) return; // avoid a bad retroaction
2916
2917   /* in preparation for end_text(), send focus to the canvas if it's not ours.
2918      (avoid issues with Gtk trying to send focus to the dead text widget) */
2919
2920   if (!GTK_WIDGET_HAS_FOCUS(spinbutton))
2921     gtk_widget_grab_focus(GTK_WIDGET(canvas));
2922   end_text();
2923
2924   val = gtk_spin_button_get_value_as_int(spinbutton) - 1;
2925
2926   if (val == journal.npages) { // create a page at end
2927     on_journalNewPageEnd_activate(NULL, NULL);
2928     return;
2929   }
2930
2931   if (val == ui.pageno) return;
2932   if (val < 0) val = 0;
2933   if (val > journal.npages-1) val = journal.npages-1;
2934   do_switch_page(val, TRUE, FALSE);
2935 }
2936
2937
2938 void
2939 on_journalDefaultBackground_activate   (GtkMenuItem     *menuitem,
2940                                         gpointer         user_data)
2941 {
2942   struct Page *pg;
2943   GList *pglist;
2944   
2945   end_text();
2946   reset_selection();
2947   
2948   pg = ui.cur_page;
2949   for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
2950     if (ui.bg_apply_all_pages) pg = (struct Page *)pglist->data;
2951     prepare_new_undo();
2952     if (ui.bg_apply_all_pages) {
2953       if (pglist->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
2954       if (pglist->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
2955     }
2956     undo->type = ITEM_NEW_BG_RESIZE;
2957     undo->page = pg;
2958     undo->bg = pg->bg;
2959     undo->val_x = pg->width;
2960     undo->val_y = pg->height; 
2961     pg->bg = (struct Background *)g_memdup(ui.default_page.bg, sizeof(struct Background));
2962     pg->width = ui.default_page.width;
2963     pg->height = ui.default_page.height;
2964     pg->bg->canvas_item = undo->bg->canvas_item;
2965     undo->bg->canvas_item = NULL;
2966   
2967     make_page_clipbox(pg);
2968     update_canvas_bg(pg);
2969     if (!ui.bg_apply_all_pages) break;
2970   }
2971   do_switch_page(ui.pageno, TRUE, TRUE);
2972 }
2973
2974
2975 void
2976 on_journalSetAsDefault_activate        (GtkMenuItem     *menuitem,
2977                                         gpointer         user_data)
2978 {
2979   if (ui.cur_page->bg->type != BG_SOLID) return;
2980   
2981   end_text();
2982   prepare_new_undo();
2983   undo->type = ITEM_NEW_DEFAULT_BG;
2984   undo->val_x = ui.default_page.width;
2985   undo->val_y = ui.default_page.height;
2986   undo->bg = ui.default_page.bg;
2987   
2988   ui.default_page.width = ui.cur_page->width;
2989   ui.default_page.height = ui.cur_page->height;
2990   ui.default_page.bg = (struct Background *)g_memdup(ui.cur_page->bg, sizeof(struct Background));
2991   ui.default_page.bg->canvas_item = NULL;
2992 }
2993
2994
2995 void
2996 on_comboStdSizes_changed               (GtkComboBox     *combobox,
2997                                         gpointer         user_data)
2998 {
2999   GtkEntry *entry;
3000   GtkComboBox *comboUnit;
3001   int val;
3002   gchar text[20];
3003
3004   if (papersize_need_init) {
3005     gtk_combo_box_set_active(combobox, papersize_std);
3006     papersize_need_init = FALSE;
3007   } else {
3008     val = gtk_combo_box_get_active(combobox);
3009     if (val == -1 || val == papersize_std) return;
3010     papersize_std = val;
3011     if (val == STD_SIZE_CUSTOM) return;
3012     papersize_unit = std_units[val];
3013     papersize_width = std_widths[val];
3014     papersize_height = std_heights[val];
3015   }
3016   comboUnit = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboUnit"));
3017   gtk_combo_box_set_active(comboUnit, papersize_unit);
3018   entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryWidth"));
3019   g_snprintf(text, 20, "%.2f", papersize_width/unit_sizes[papersize_unit]);
3020   if (g_str_has_suffix(text, ".00")) 
3021     g_snprintf(text, 20, "%d", (int) (papersize_width/unit_sizes[papersize_unit]));
3022   gtk_entry_set_text(entry, text);
3023   entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryHeight"));
3024   g_snprintf(text, 20, "%.2f", papersize_height/unit_sizes[papersize_unit]);
3025   if (g_str_has_suffix(text, ".00")) 
3026     g_snprintf(text, 20, "%d", (int) (papersize_height/unit_sizes[papersize_unit]));
3027   gtk_entry_set_text(entry, text);
3028 }
3029
3030
3031 void
3032 on_entryWidth_changed                  (GtkEditable     *editable,
3033                                         gpointer         user_data)
3034 {
3035   double val;
3036   const gchar *text;
3037   gchar *ptr;
3038   GtkComboBox *comboStdSizes;
3039   
3040   text = gtk_entry_get_text(GTK_ENTRY(editable));
3041   val = strtod(text, &ptr);
3042   papersize_width_valid = (*ptr == 0 && val > 0.);
3043   if (!papersize_width_valid) return; // invalid entry
3044   val *= unit_sizes[papersize_unit];
3045   if (fabs(val - papersize_width) < 0.1) return; // no change
3046   papersize_std = STD_SIZE_CUSTOM;
3047   papersize_width = val;
3048   comboStdSizes = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboStdSizes"));
3049   gtk_combo_box_set_active(comboStdSizes, papersize_std);
3050 }
3051
3052
3053 void
3054 on_entryHeight_changed                 (GtkEditable     *editable,
3055                                         gpointer         user_data)
3056 {
3057   double val;
3058   const gchar *text;
3059   gchar *ptr;
3060   GtkComboBox *comboStdSizes;
3061   
3062   text = gtk_entry_get_text(GTK_ENTRY(editable));
3063   val = strtod(text, &ptr);
3064   papersize_height_valid = (*ptr == 0 && val > 0.);
3065   if (!papersize_height_valid) return; // invalid entry
3066   val *= unit_sizes[papersize_unit];
3067   if (fabs(val - papersize_height) < 0.1) return; // no change
3068   papersize_std = STD_SIZE_CUSTOM;
3069   papersize_height = val;
3070   comboStdSizes = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboStdSizes"));
3071   gtk_combo_box_set_active(comboStdSizes, papersize_std);
3072 }
3073
3074
3075 void
3076 on_comboUnit_changed                   (GtkComboBox     *combobox,
3077                                         gpointer         user_data)
3078 {
3079   GtkEntry *entry;
3080   int val;
3081   gchar text[20];
3082
3083   val = gtk_combo_box_get_active(combobox);
3084   if (val == -1 || val == papersize_unit) return;
3085   papersize_unit = val;
3086   entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryWidth"));
3087   if (papersize_width_valid) {
3088     g_snprintf(text, 20, "%.2f", papersize_width/unit_sizes[papersize_unit]);
3089     if (g_str_has_suffix(text, ".00")) 
3090       g_snprintf(text, 20, "%d", (int) (papersize_width/unit_sizes[papersize_unit]));
3091   } else *text = 0;
3092   gtk_entry_set_text(entry, text);
3093   if (papersize_height_valid) {
3094     entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryHeight"));
3095     g_snprintf(text, 20, "%.2f", papersize_height/unit_sizes[papersize_unit]);
3096     if (g_str_has_suffix(text, ".00")) 
3097       g_snprintf(text, 20, "%d", (int) (papersize_height/unit_sizes[papersize_unit]));
3098   } else *text = 0;
3099   gtk_entry_set_text(entry, text);
3100 }
3101
3102
3103 void
3104 on_viewFullscreen_activate             (GtkMenuItem     *menuitem,
3105                                         gpointer         user_data)
3106 {
3107   gboolean active;
3108   
3109   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
3110     active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3111   else
3112     active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
3113
3114   if (active == ui.fullscreen) return;
3115   do_fullscreen(active);
3116 }
3117
3118
3119 void
3120 on_optionsButtonMappings_activate      (GtkMenuItem     *menuitem,
3121                                         gpointer         user_data)
3122 {
3123   end_text();
3124   ui.use_erasertip =
3125     gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3126   update_mappings_menu();
3127 }
3128
3129
3130 void
3131 on_optionsProgressiveBG_activate       (GtkMenuItem     *menuitem,
3132                                         gpointer         user_data)
3133 {
3134   gboolean active;
3135   
3136   active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3137   if (ui.progressive_bg == active) return;
3138   end_text();
3139   ui.progressive_bg = active;
3140   if (!ui.progressive_bg) rescale_bg_pixmaps();
3141 }
3142
3143
3144 void
3145 on_mru_activate                        (GtkMenuItem     *menuitem,
3146                                         gpointer         user_data)
3147 {
3148   int which;
3149   gboolean success;
3150   GtkWidget *dialog;
3151   
3152   end_text();
3153   if (!ok_to_close()) return; // user aborted on save confirmation
3154   
3155   for (which = 0 ; which < MRU_SIZE; which++) {
3156     if (ui.mrumenu[which] == GTK_WIDGET(menuitem)) break;
3157   }
3158   if (which == MRU_SIZE || ui.mru[which] == NULL) return; // not found...
3159
3160   set_cursor_busy(TRUE);
3161   success = open_journal(ui.mru[which]);
3162   set_cursor_busy(FALSE);
3163   if (success) return;
3164
3165   /* open failed */
3166   dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
3167     GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening file '%s'"), ui.mru[which]);
3168   gtk_dialog_run(GTK_DIALOG(dialog));
3169   gtk_widget_destroy(dialog);
3170   delete_mru_entry(which);
3171 }
3172
3173
3174 void
3175 on_button2Pen_activate                 (GtkMenuItem     *menuitem,
3176                                         gpointer         user_data)
3177 {
3178   process_mapping_activate(menuitem, 1, TOOL_PEN);
3179 }
3180
3181
3182 void
3183 on_button2Eraser_activate              (GtkMenuItem     *menuitem,
3184                                         gpointer         user_data)
3185 {
3186   process_mapping_activate(menuitem, 1, TOOL_ERASER);
3187 }
3188
3189
3190 void
3191 on_button2Highlighter_activate         (GtkMenuItem     *menuitem,
3192                                         gpointer         user_data)
3193 {
3194   process_mapping_activate(menuitem, 1, TOOL_HIGHLIGHTER);
3195 }
3196
3197
3198 void
3199 on_button2Text_activate                (GtkMenuItem     *menuitem,
3200                                         gpointer         user_data)
3201 {
3202   process_mapping_activate(menuitem, 1, TOOL_TEXT);
3203 }
3204
3205
3206 void
3207 on_button2SelectRegion_activate        (GtkMenuItem     *menuitem,
3208                                         gpointer         user_data)
3209 {
3210   process_mapping_activate(menuitem, 1, TOOL_SELECTREGION);
3211 }
3212
3213
3214 void
3215 on_button2SelectRectangle_activate     (GtkMenuItem     *menuitem,
3216                                         gpointer         user_data)
3217 {
3218   process_mapping_activate(menuitem, 1, TOOL_SELECTRECT);
3219 }
3220
3221
3222 void
3223 on_button2VerticalSpace_activate       (GtkMenuItem     *menuitem,
3224                                         gpointer         user_data)
3225 {
3226   process_mapping_activate(menuitem, 1, TOOL_VERTSPACE);
3227 }
3228
3229
3230 void
3231 on_button2LinkBrush_activate           (GtkMenuItem     *menuitem,
3232                                         gpointer         user_data)
3233 {
3234   int i;
3235   
3236   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3237   end_text();
3238   ui.linked_brush[1] = BRUSH_LINKED;
3239   for (i=0;i<NUM_STROKE_TOOLS;i++) update_mapping_linkings(i);
3240 }
3241
3242
3243 void
3244 on_button2CopyBrush_activate           (GtkMenuItem     *menuitem,
3245                                         gpointer         user_data)
3246 {
3247   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3248   end_text();
3249   if (ui.toolno[1] >= NUM_STROKE_TOOLS) {
3250     ui.linked_brush[1] = BRUSH_STATIC;
3251     update_mappings_menu_linkings();
3252     return;
3253   }
3254   ui.linked_brush[1] = BRUSH_COPIED;
3255   g_memmove(&(ui.brushes[1][ui.toolno[1]]), &(ui.brushes[0][ui.toolno[1]]), sizeof(struct Brush));
3256 }
3257
3258
3259 void
3260 on_button3Pen_activate                 (GtkMenuItem     *menuitem,
3261                                         gpointer         user_data)
3262 {
3263   process_mapping_activate(menuitem, 2, TOOL_PEN);
3264 }
3265
3266
3267 void
3268 on_button3Eraser_activate              (GtkMenuItem     *menuitem,
3269                                         gpointer         user_data)
3270 {
3271   process_mapping_activate(menuitem, 2, TOOL_ERASER);
3272 }
3273
3274
3275 void
3276 on_button3Highlighter_activate         (GtkMenuItem     *menuitem,
3277                                         gpointer         user_data)
3278 {
3279   process_mapping_activate(menuitem, 2, TOOL_HIGHLIGHTER);
3280 }
3281
3282
3283 void
3284 on_button3Text_activate                (GtkMenuItem     *menuitem,
3285                                         gpointer         user_data)
3286 {
3287   process_mapping_activate(menuitem, 2, TOOL_TEXT);
3288 }
3289
3290
3291 void
3292 on_button3SelectRegion_activate        (GtkMenuItem     *menuitem,
3293                                         gpointer         user_data)
3294 {
3295   process_mapping_activate(menuitem, 2, TOOL_SELECTREGION);
3296 }
3297
3298
3299 void
3300 on_button3SelectRectangle_activate     (GtkMenuItem     *menuitem,
3301                                         gpointer         user_data)
3302 {
3303   process_mapping_activate(menuitem, 2, TOOL_SELECTRECT);
3304 }
3305
3306
3307 void
3308 on_button3VerticalSpace_activate       (GtkMenuItem     *menuitem,
3309                                         gpointer         user_data)
3310 {
3311   process_mapping_activate(menuitem, 2, TOOL_VERTSPACE);
3312 }
3313
3314
3315 void
3316 on_button3LinkBrush_activate           (GtkMenuItem     *menuitem,
3317                                         gpointer         user_data)
3318 {
3319   int i;
3320   
3321   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3322   end_text();
3323   ui.linked_brush[2] = BRUSH_LINKED;
3324   for (i=0;i<NUM_STROKE_TOOLS;i++) update_mapping_linkings(i);
3325 }
3326
3327
3328 void
3329 on_button3CopyBrush_activate           (GtkMenuItem     *menuitem,
3330                                         gpointer         user_data)
3331 {
3332   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3333   end_text();
3334   if (ui.toolno[2] >= NUM_STROKE_TOOLS) {
3335     ui.linked_brush[2] = BRUSH_STATIC;
3336     update_mappings_menu_linkings();
3337     return;
3338   }
3339   ui.linked_brush[2] = BRUSH_COPIED;
3340   g_memmove(&(ui.brushes[2][ui.toolno[2]]), &(ui.brushes[0][ui.toolno[2]]), sizeof(struct Brush));
3341 }
3342
3343 // the set zoom dialog
3344
3345 GtkWidget *zoom_dialog;
3346 double zoom_percent;
3347
3348 void
3349 on_viewSetZoom_activate                (GtkMenuItem     *menuitem,
3350                                         gpointer         user_data)
3351 {
3352   int response;
3353   double test_w, test_h;
3354   GtkSpinButton *spinZoom;
3355   
3356   end_text();
3357   zoom_dialog = create_zoomDialog();
3358   zoom_percent = 100*ui.zoom / DEFAULT_ZOOM;
3359   spinZoom = GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(zoom_dialog), "spinZoom"));
3360   gtk_spin_button_set_increments(spinZoom, ui.zoom_step_increment, 5*ui.zoom_step_increment);
3361   gtk_spin_button_set_value(spinZoom, zoom_percent);
3362   test_w = 100*(GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width/DEFAULT_ZOOM;
3363   test_h = 100*(GTK_WIDGET(canvas))->allocation.height/ui.cur_page->height/DEFAULT_ZOOM;
3364   if (zoom_percent > 99.9 && zoom_percent < 100.1) 
3365     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3366            G_OBJECT(zoom_dialog), "radioZoom100")), TRUE);
3367   else if (zoom_percent > test_w-0.1 && zoom_percent < test_w+0.1)
3368     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3369            G_OBJECT(zoom_dialog), "radioZoomWidth")), TRUE);
3370   else if (zoom_percent > test_h-0.1 && zoom_percent < test_h+0.1)
3371     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3372            G_OBJECT(zoom_dialog), "radioZoomHeight")), TRUE);
3373   else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3374            G_OBJECT(zoom_dialog), "radioZoom")), TRUE);
3375   gtk_widget_show(zoom_dialog);
3376   
3377   do {
3378     response = gtk_dialog_run(GTK_DIALOG(zoom_dialog));
3379     if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY) {
3380       ui.zoom = DEFAULT_ZOOM*zoom_percent/100;
3381       gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
3382       rescale_text_items();
3383       rescale_bg_pixmaps();
3384     }
3385   } while (response == GTK_RESPONSE_APPLY);
3386   
3387   gtk_widget_destroy(zoom_dialog);
3388 }
3389
3390
3391 void
3392 on_spinZoom_value_changed              (GtkSpinButton   *spinbutton,
3393                                         gpointer         user_data)
3394 {
3395   double val;
3396
3397   val = gtk_spin_button_get_value(GTK_SPIN_BUTTON(g_object_get_data(
3398              G_OBJECT(zoom_dialog), "spinZoom")));
3399   if (val<1) return;
3400   if (val<10) val=10.;
3401   if (val>1500) val=1500.;
3402   if (val<zoom_percent-1 || val>zoom_percent+1)
3403     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3404            G_OBJECT(zoom_dialog), "radioZoom")), TRUE);
3405   zoom_percent = val;
3406 }
3407
3408
3409 void
3410 on_radioZoom_toggled                   (GtkToggleButton *togglebutton,
3411                                         gpointer         user_data)
3412 {
3413   // nothing to do
3414 }
3415
3416
3417 void
3418 on_radioZoom100_toggled                (GtkToggleButton *togglebutton,
3419                                         gpointer         user_data)
3420 {
3421   if (!gtk_toggle_button_get_active(togglebutton)) return;
3422   zoom_percent = 100.;
3423   gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3424         G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3425 }
3426
3427
3428 void
3429 on_radioZoomWidth_toggled              (GtkToggleButton *togglebutton,
3430                                         gpointer         user_data)
3431 {
3432   if (!gtk_toggle_button_get_active(togglebutton)) return;
3433   zoom_percent = 100*(GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width/DEFAULT_ZOOM;
3434   gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3435         G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3436 }
3437
3438
3439 void
3440 on_radioZoomHeight_toggled             (GtkToggleButton *togglebutton,
3441                                         gpointer         user_data)
3442 {
3443   if (!gtk_toggle_button_get_active(togglebutton)) return;
3444   zoom_percent = 100*(GTK_WIDGET(canvas))->allocation.height/ui.cur_page->height/DEFAULT_ZOOM;
3445   gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3446         G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3447 }
3448
3449
3450 void
3451 on_toolsHand_activate                  (GtkMenuItem     *menuitem,
3452                                         gpointer         user_data)
3453 {
3454   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
3455     if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
3456       return;
3457   } else {
3458     if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
3459       return;
3460   }
3461
3462   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
3463   if (ui.toolno[ui.cur_mapping] == TOOL_HAND) return;
3464
3465   ui.cur_mapping = 0;
3466   end_text();
3467   reset_selection();
3468   ui.toolno[ui.cur_mapping] = TOOL_HAND;
3469   update_mapping_linkings(-1);
3470   update_tool_buttons();
3471   update_tool_menu();
3472   update_color_menu();
3473   update_cursor();
3474 }
3475
3476
3477 void
3478 on_button2Hand_activate                (GtkMenuItem     *menuitem,
3479                                         gpointer         user_data)
3480 {
3481   process_mapping_activate(menuitem, 1, TOOL_HAND);
3482 }
3483
3484
3485 void
3486 on_button3Hand_activate                (GtkMenuItem     *menuitem,
3487                                         gpointer         user_data)
3488 {
3489   process_mapping_activate(menuitem, 2, TOOL_HAND);
3490 }
3491
3492
3493 void
3494 on_optionsPrintRuling_activate         (GtkMenuItem     *menuitem,
3495                                         gpointer         user_data)
3496 {
3497   end_text();
3498   ui.print_ruling = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3499 }
3500
3501 void
3502 on_optionsAutoloadPdfXoj_activate      (GtkMenuItem     *menuitem,
3503                                         gpointer         user_data)
3504 {
3505   end_text();
3506   ui.autoload_pdf_xoj = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3507 }
3508
3509 void
3510 on_fontButton_font_set                 (GtkFontButton   *fontbutton,
3511                                         gpointer         user_data)
3512 {
3513   gchar *str;
3514   
3515   str = g_strdup(gtk_font_button_get_font_name(fontbutton));
3516   process_font_sel(str);
3517 }
3518
3519 void
3520 on_optionsLeftHanded_activate          (GtkMenuItem     *menuitem,   
3521                                         gpointer         user_data)
3522 {
3523   end_text();
3524   ui.left_handed = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3525   gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW(GET_COMPONENT("scrolledwindowMain")),
3526     ui.left_handed?GTK_CORNER_TOP_RIGHT:GTK_CORNER_TOP_LEFT);
3527 }
3528
3529 void
3530 on_optionsShortenMenus_activate        (GtkMenuItem     *menuitem,  
3531                                         gpointer         user_data)
3532 {
3533   gchar *item, *nextptr;
3534   GtkWidget *w;
3535   
3536   end_text();
3537   ui.shorten_menus = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3538   
3539   /* go over the item list */
3540   item = ui.shorten_menu_items;
3541   while (*item==' ') item++;
3542   while (*item) {
3543     nextptr = strchr(item, ' ');
3544     if (nextptr!=NULL) *nextptr = 0;
3545     // hide or show the item
3546     w = GET_COMPONENT(item);
3547     if (w != NULL) {
3548       if (ui.shorten_menus) gtk_widget_hide(w);
3549       else gtk_widget_show(w);
3550     }
3551     // next item
3552     if (nextptr==NULL) break;
3553     *nextptr = ' ';
3554     item = nextptr;
3555     while (*item==' ') item++;
3556   }
3557   
3558   // just in case someone tried to unhide stuff they shouldn't be seeing
3559   hide_unimplemented();
3560   // maybe we should also make sure the drawing area stays visible ?
3561 }
3562
3563 void
3564 on_optionsAutoSavePrefs_activate       (GtkMenuItem     *menuitem,  
3565                                         gpointer         user_data)
3566 {
3567   end_text();
3568   ui.auto_save_prefs = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3569 }
3570
3571 void
3572 on_optionsPressureSensitive_activate   (GtkMenuItem     *menuitem,
3573                                         gpointer         user_data)
3574 {
3575   int i;
3576   end_text();
3577   ui.pressure_sensitivity =
3578     gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3579   for (i=0; i<=NUM_BUTTONS; i++)
3580     ui.brushes[i][TOOL_PEN].variable_width = ui.pressure_sensitivity;
3581   update_mappings_menu();
3582 }
3583
3584
3585 void
3586 on_buttonColorChooser_set              (GtkColorButton  *colorbutton,
3587                                         gpointer         user_data)
3588 {
3589   GdkColor gdkcolor;
3590   guint16 alpha;
3591   
3592   gtk_color_button_get_color(colorbutton, &gdkcolor);
3593   alpha = gtk_color_button_get_alpha(colorbutton);
3594   process_color_activate((GtkMenuItem*)colorbutton, COLOR_OTHER, gdkcolor_to_rgba(gdkcolor, alpha));
3595 }
3596
3597
3598 void
3599 on_optionsButtonsSwitchMappings_activate(GtkMenuItem    *menuitem,
3600                                         gpointer         user_data)
3601 {
3602   end_text();
3603   switch_mapping(0);
3604   ui.button_switch_mapping = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3605 }
3606