]> git.donarmstrong.com Git - xournal.git/blob - src/xo-callbacks.c
Image patch
[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 || undo->type == ITEM_IMAGE) {
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 || redo->type == ITEM_IMAGE) {
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       if (it->type == ITEM_IMAGE && it->canvas_item != NULL) {
844         // remark: a variable-width item might have lost its variable-width
845         group = (GnomeCanvasGroup *) it->canvas_item->parent;
846         gtk_object_destroy(GTK_OBJECT(it->canvas_item));
847         make_canvas_item_one(group, it);
848       }
849     }
850   }
851   else if (redo->type == ITEM_TEXT_EDIT) {
852     tmpstr = redo->str;
853     redo->str = redo->item->text;
854     redo->item->text = tmpstr;
855     gnome_canvas_item_set(redo->item->canvas_item, "text", tmpstr, NULL);
856     update_item_bbox(redo->item);
857   }
858   else if (redo->type == ITEM_TEXT_ATTRIB) {
859     tmpstr = redo->str;
860     redo->str = redo->item->font_name;
861     redo->item->font_name = tmpstr;
862     tmp_x = redo->val_x;
863     redo->val_x = redo->item->font_size;
864     redo->item->font_size = tmp_x;
865     g_memmove(&tmp_brush, redo->brush, sizeof(struct Brush));
866     g_memmove(redo->brush, &(redo->item->brush), sizeof(struct Brush));
867     g_memmove(&(redo->item->brush), &tmp_brush, sizeof(struct Brush));
868     gnome_canvas_item_set(redo->item->canvas_item, 
869       "fill-color-rgba", redo->item->brush.color_rgba, NULL);
870     update_text_item_displayfont(redo->item);
871     update_item_bbox(redo->item);
872   }
873   
874   // move item from redo to undo stack
875   u = redo;
876   redo = redo->next;
877   u->next = undo;
878   undo = u;
879   ui.saved = FALSE;
880   update_undo_redo_enabled();
881   if (u->multiop & MULTIOP_CONT_REDO) on_editRedo_activate(NULL,NULL); // loop
882 }
883
884
885 void
886 on_editCut_activate                    (GtkMenuItem     *menuitem,
887                                         gpointer         user_data)
888 {
889   end_text();
890   selection_to_clip();
891   selection_delete();
892 }
893
894
895 void
896 on_editCopy_activate                   (GtkMenuItem     *menuitem,
897                                         gpointer         user_data)
898 {
899   end_text();
900   selection_to_clip();
901 }
902
903
904 void
905 on_editPaste_activate                  (GtkMenuItem     *menuitem,
906                                         gpointer         user_data)
907 {
908   end_text();
909   clipboard_paste();
910 }
911
912
913 void
914 on_editDelete_activate                 (GtkMenuItem     *menuitem,
915                                         gpointer         user_data)
916 {
917   end_text();
918   selection_delete();
919 }
920
921
922 void
923 on_viewContinuous_activate             (GtkMenuItem     *menuitem,
924                                         gpointer         user_data)
925 {
926   GtkAdjustment *v_adj;
927   double yscroll;
928   struct Page *pg;
929
930   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
931   if (ui.view_continuous) return;
932   ui.view_continuous = TRUE;
933   v_adj = gtk_layout_get_vadjustment(GTK_LAYOUT(canvas));
934   pg = ui.cur_page;
935   yscroll = gtk_adjustment_get_value(v_adj) - pg->voffset*ui.zoom;
936   update_page_stuff();
937   gtk_adjustment_set_value(v_adj, yscroll + pg->voffset*ui.zoom);
938   // force a refresh
939   gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
940 }
941
942
943 void
944 on_viewOnePage_activate                (GtkMenuItem     *menuitem,
945                                         gpointer         user_data)
946 {
947   GtkAdjustment *v_adj;
948   double yscroll;
949   
950   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
951   if (!ui.view_continuous) return;
952   ui.view_continuous = FALSE;
953   v_adj = gtk_layout_get_vadjustment(GTK_LAYOUT(canvas));
954   yscroll = gtk_adjustment_get_value(v_adj) - ui.cur_page->voffset*ui.zoom;
955   update_page_stuff();
956   gtk_adjustment_set_value(v_adj, yscroll + ui.cur_page->voffset*ui.zoom);
957   // force a refresh
958   gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
959 }
960
961
962 void
963 on_viewZoomIn_activate                 (GtkMenuItem     *menuitem,
964                                         gpointer         user_data)
965 {
966   if (ui.zoom > MAX_ZOOM) return;
967   ui.zoom *= ui.zoom_step_factor;
968   gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
969   rescale_text_items();
970   rescale_bg_pixmaps();
971   rescale_images();
972 }
973
974
975 void
976 on_viewZoomOut_activate                (GtkMenuItem     *menuitem,
977                                         gpointer         user_data)
978 {
979   if (ui.zoom < MIN_ZOOM) return;
980   ui.zoom /= ui.zoom_step_factor;
981   gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
982   rescale_text_items();
983   rescale_bg_pixmaps();
984   rescale_images();
985 }
986
987
988 void
989 on_viewNormalSize_activate             (GtkMenuItem     *menuitem,
990                                         gpointer         user_data)
991 {
992   ui.zoom = DEFAULT_ZOOM;
993   gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
994   rescale_text_items();
995   rescale_bg_pixmaps();
996   rescale_images();
997 }
998
999
1000 void
1001 on_viewPageWidth_activate              (GtkMenuItem     *menuitem,
1002                                         gpointer         user_data)
1003 {
1004   ui.zoom = (GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width;
1005   gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
1006   rescale_text_items();
1007   rescale_bg_pixmaps();
1008   rescale_images();
1009 }
1010
1011
1012 void
1013 on_viewFirstPage_activate              (GtkMenuItem     *menuitem,
1014                                         gpointer         user_data)
1015 {
1016   end_text();
1017   do_switch_page(0, TRUE, FALSE);
1018 }
1019
1020
1021 void
1022 on_viewPreviousPage_activate           (GtkMenuItem     *menuitem,
1023                                         gpointer         user_data)
1024 {
1025   end_text();
1026   if (ui.pageno == 0) return;
1027   do_switch_page(ui.pageno-1, TRUE, FALSE);
1028 }
1029
1030
1031 void
1032 on_viewNextPage_activate               (GtkMenuItem     *menuitem,
1033                                         gpointer         user_data)
1034 {
1035   end_text();
1036   if (ui.pageno == journal.npages-1) { // create a page at end
1037     on_journalNewPageEnd_activate(menuitem, user_data);
1038     return;
1039   }
1040   do_switch_page(ui.pageno+1, TRUE, FALSE);
1041 }
1042
1043
1044 void
1045 on_viewLastPage_activate               (GtkMenuItem     *menuitem,
1046                                         gpointer         user_data)
1047 {
1048   end_text();
1049   do_switch_page(journal.npages-1, TRUE, FALSE);
1050 }
1051
1052
1053 void
1054 on_viewShowLayer_activate              (GtkMenuItem     *menuitem,
1055                                         gpointer         user_data)
1056 {
1057   end_text();
1058   if (ui.layerno == ui.cur_page->nlayers-1) return;
1059   reset_selection();
1060   ui.layerno++;
1061   ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
1062   gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group));
1063   update_page_stuff();
1064 }
1065
1066
1067 void
1068 on_viewHideLayer_activate              (GtkMenuItem     *menuitem,
1069                                         gpointer         user_data)
1070 {
1071   end_text();
1072   if (ui.layerno == -1) return;
1073   reset_selection();
1074   gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group));
1075   ui.layerno--;
1076   if (ui.layerno<0) ui.cur_layer = NULL;
1077   else ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
1078   update_page_stuff();
1079 }
1080
1081
1082 void
1083 on_journalNewPageBefore_activate       (GtkMenuItem     *menuitem,
1084                                         gpointer         user_data)
1085 {
1086   struct Page *pg;
1087
1088   end_text();
1089   reset_selection();
1090   pg = new_page(ui.cur_page);
1091   journal.pages = g_list_insert(journal.pages, pg, ui.pageno);
1092   journal.npages++;
1093   do_switch_page(ui.pageno, TRUE, TRUE);
1094   
1095   prepare_new_undo();
1096   undo->type = ITEM_NEW_PAGE;
1097   undo->val = ui.pageno;
1098   undo->page = pg;
1099 }
1100
1101
1102 void
1103 on_journalNewPageAfter_activate        (GtkMenuItem     *menuitem,
1104                                         gpointer         user_data)
1105 {
1106   struct Page *pg;
1107
1108   end_text();
1109   reset_selection();
1110   pg = new_page(ui.cur_page);
1111   journal.pages = g_list_insert(journal.pages, pg, ui.pageno+1);
1112   journal.npages++;
1113   do_switch_page(ui.pageno+1, TRUE, TRUE);
1114
1115   prepare_new_undo();
1116   undo->type = ITEM_NEW_PAGE;
1117   undo->val = ui.pageno;
1118   undo->page = pg;
1119 }
1120
1121
1122 void
1123 on_journalNewPageEnd_activate          (GtkMenuItem     *menuitem,
1124                                         gpointer         user_data)
1125 {
1126   struct Page *pg;
1127
1128   end_text();
1129   reset_selection();
1130   pg = new_page((struct Page *)g_list_last(journal.pages)->data);
1131   journal.pages = g_list_append(journal.pages, pg);
1132   journal.npages++;
1133   do_switch_page(journal.npages-1, TRUE, TRUE);
1134
1135   prepare_new_undo();
1136   undo->type = ITEM_NEW_PAGE;
1137   undo->val = ui.pageno;
1138   undo->page = pg;
1139 }
1140
1141
1142 void
1143 on_journalDeletePage_activate          (GtkMenuItem     *menuitem,
1144                                         gpointer         user_data)
1145 {
1146   GList *layerlist, *itemlist;
1147   struct Layer *l;
1148
1149   end_text();
1150   if (journal.npages == 1) return;
1151   reset_selection();  
1152   reset_recognizer(); // safer
1153   prepare_new_undo();
1154   undo->type = ITEM_DELETE_PAGE;
1155   undo->val = ui.pageno;
1156   undo->page = ui.cur_page;
1157
1158   // unmap all the canvas items  
1159   gtk_object_destroy(GTK_OBJECT(ui.cur_page->group));
1160   ui.cur_page->group = NULL;
1161   ui.cur_page->bg->canvas_item = NULL;
1162   for (layerlist = ui.cur_page->layers; layerlist!=NULL; layerlist = layerlist->next) {
1163     l = (struct Layer *)layerlist->data;
1164     for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next)
1165       ((struct Item *)itemlist->data)->canvas_item = NULL;
1166     l->group = NULL;
1167   }
1168   
1169   journal.pages = g_list_remove(journal.pages, ui.cur_page);
1170   journal.npages--;
1171   if (ui.pageno == journal.npages) ui.pageno--;
1172   ui.cur_page = NULL;
1173      // so do_switch_page() won't try to remap the layers of the defunct page
1174   do_switch_page(ui.pageno, TRUE, TRUE);
1175 }
1176
1177
1178 void
1179 on_journalNewLayer_activate            (GtkMenuItem     *menuitem,
1180                                         gpointer         user_data)
1181 {
1182   struct Layer *l;
1183   
1184   end_text();
1185   reset_selection();
1186   l = g_new(struct Layer, 1);
1187   l->items = NULL;
1188   l->nitems = 0;
1189   l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
1190     ui.cur_page->group, gnome_canvas_group_get_type(), NULL);
1191   lower_canvas_item_to(ui.cur_page->group, GNOME_CANVAS_ITEM(l->group),
1192     (ui.cur_layer!=NULL)?(GNOME_CANVAS_ITEM(ui.cur_layer->group)):(ui.cur_page->bg->canvas_item));
1193   ui.cur_page->layers = g_list_insert(ui.cur_page->layers, l, ui.layerno+1);
1194   ui.cur_layer = l;
1195   ui.layerno++;
1196   ui.cur_page->nlayers++;
1197   update_page_stuff();
1198
1199   prepare_new_undo();
1200   undo->type = ITEM_NEW_LAYER;
1201   undo->val = ui.layerno;
1202   undo->layer = l;
1203   undo->page = ui.cur_page;  
1204 }
1205
1206
1207 void
1208 on_journalDeleteLayer_activate         (GtkMenuItem     *menuitem,
1209                                         gpointer         user_data)
1210 {
1211   GList *list;
1212   
1213   end_text();
1214   if (ui.cur_layer == NULL) return;
1215   reset_selection();
1216   reset_recognizer(); // safer
1217   prepare_new_undo();
1218   undo->type = ITEM_DELETE_LAYER;
1219   undo->val = ui.layerno;
1220   undo->layer = ui.cur_layer;
1221   undo->layer2 = NULL;
1222   undo->page = ui.cur_page;
1223   // delete all the canvas items
1224   gtk_object_destroy(GTK_OBJECT(ui.cur_layer->group));
1225   ui.cur_layer->group = NULL;
1226   for (list=ui.cur_layer->items; list!=NULL; list=list->next)
1227     ((struct Item *)list->data)->canvas_item = NULL;
1228
1229   ui.cur_page->layers = g_list_remove(ui.cur_page->layers, ui.cur_layer);
1230
1231   if (ui.cur_page->nlayers>=2) {
1232     ui.cur_page->nlayers--;
1233     ui.layerno--;
1234     if (ui.layerno<0) ui.cur_layer = NULL;
1235     else ui.cur_layer = (struct Layer *)g_list_nth_data(ui.cur_page->layers, ui.layerno);
1236   } 
1237   else { // special case: can't remove the last layer
1238     ui.cur_layer = g_new(struct Layer, 1);
1239     ui.cur_layer->items = NULL;
1240     ui.cur_layer->nitems = 0;
1241     ui.cur_layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
1242       ui.cur_page->group, gnome_canvas_group_get_type(), NULL);
1243     ui.cur_page->layers = g_list_append(NULL, ui.cur_layer);
1244     undo->val = -1;
1245     undo->layer2 = ui.cur_layer;
1246   }
1247
1248   update_page_stuff();
1249 }
1250
1251
1252 void
1253 on_journalFlatten_activate             (GtkMenuItem     *menuitem,
1254                                         gpointer         user_data)
1255 {
1256
1257 }
1258
1259
1260 // the paper sizes dialog
1261
1262 GtkWidget *papersize_dialog;
1263 int papersize_std, papersize_unit;
1264 double papersize_width, papersize_height;
1265 gboolean papersize_need_init, papersize_width_valid, papersize_height_valid;
1266
1267 #define STD_SIZE_A4 0
1268 #define STD_SIZE_A4R 1
1269 #define STD_SIZE_LETTER 2
1270 #define STD_SIZE_LETTER_R 3
1271 #define STD_SIZE_CUSTOM 4
1272
1273 double unit_sizes[4] = {28.346, 72., 72./DISPLAY_DPI_DEFAULT, 1.};
1274 double std_widths[STD_SIZE_CUSTOM] =  {595.27, 841.89, 612., 792.};
1275 double std_heights[STD_SIZE_CUSTOM] = {841.89, 595.27, 792., 612.};
1276 double std_units[STD_SIZE_CUSTOM] = {UNIT_CM, UNIT_CM, UNIT_IN, UNIT_IN};
1277
1278 void
1279 on_journalPaperSize_activate           (GtkMenuItem     *menuitem,
1280                                         gpointer         user_data)
1281 {
1282   int i, response;
1283   struct Page *pg;
1284   GList *pglist;
1285   
1286   end_text();
1287   papersize_dialog = create_papersizeDialog();
1288   papersize_width = ui.cur_page->width;
1289   papersize_height = ui.cur_page->height;
1290   papersize_unit = ui.default_unit;
1291   unit_sizes[UNIT_PX] = 1./DEFAULT_ZOOM;
1292 //  if (ui.cur_page->bg->type == BG_PIXMAP) papersize_unit = UNIT_PX;
1293   papersize_std = STD_SIZE_CUSTOM;
1294   for (i=0;i<STD_SIZE_CUSTOM;i++)
1295     if (fabs(papersize_width - std_widths[i])<0.1 &&
1296         fabs(papersize_height - std_heights[i])<0.1)
1297       { papersize_std = i; papersize_unit = std_units[i]; }
1298   papersize_need_init = TRUE;
1299   papersize_width_valid = papersize_height_valid = TRUE;
1300       
1301   gtk_widget_show(papersize_dialog);
1302   on_comboStdSizes_changed(GTK_COMBO_BOX(g_object_get_data(
1303        G_OBJECT(papersize_dialog), "comboStdSizes")), NULL);
1304   gtk_dialog_set_default_response(GTK_DIALOG(papersize_dialog), GTK_RESPONSE_OK);
1305        
1306   response = gtk_dialog_run(GTK_DIALOG(papersize_dialog));
1307   gtk_widget_destroy(papersize_dialog);
1308   if (response != GTK_RESPONSE_OK) return;
1309
1310   pg = ui.cur_page;
1311   for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
1312     if (ui.bg_apply_all_pages) pg = (struct Page *)pglist->data;
1313     prepare_new_undo();
1314     if (ui.bg_apply_all_pages) {
1315       if (pglist->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
1316       if (pglist->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
1317     }
1318     undo->type = ITEM_PAPER_RESIZE;
1319     undo->page = pg;
1320     undo->val_x = pg->width;
1321     undo->val_y = pg->height;
1322     if (papersize_width_valid) pg->width = papersize_width;
1323     if (papersize_height_valid) pg->height = papersize_height;
1324     make_page_clipbox(pg);
1325     update_canvas_bg(pg);
1326     if (!ui.bg_apply_all_pages) break;
1327   }
1328   do_switch_page(ui.pageno, TRUE, TRUE);
1329 }
1330
1331
1332 void
1333 on_papercolorWhite_activate            (GtkMenuItem     *menuitem,
1334                                         gpointer         user_data)
1335 {
1336   end_text();
1337   process_papercolor_activate(menuitem, COLOR_WHITE, predef_bgcolors_rgba[COLOR_WHITE]);
1338 }
1339
1340
1341 void
1342 on_papercolorYellow_activate           (GtkMenuItem     *menuitem,
1343                                         gpointer         user_data)
1344 {
1345   end_text();
1346   process_papercolor_activate(menuitem, COLOR_YELLOW, predef_bgcolors_rgba[COLOR_YELLOW]);
1347 }
1348
1349
1350 void
1351 on_papercolorPink_activate             (GtkMenuItem     *menuitem,
1352                                         gpointer         user_data)
1353 {
1354   end_text();
1355   process_papercolor_activate(menuitem, COLOR_RED, predef_bgcolors_rgba[COLOR_RED]);
1356 }
1357
1358
1359 void
1360 on_papercolorOrange_activate           (GtkMenuItem     *menuitem,
1361                                         gpointer         user_data)
1362 {
1363   end_text();
1364   process_papercolor_activate(menuitem, COLOR_ORANGE, predef_bgcolors_rgba[COLOR_ORANGE]);
1365 }
1366
1367
1368 void
1369 on_papercolorBlue_activate             (GtkMenuItem     *menuitem,
1370                                         gpointer         user_data)
1371 {
1372   end_text();
1373   process_papercolor_activate(menuitem, COLOR_BLUE, predef_bgcolors_rgba[COLOR_BLUE]);
1374 }
1375
1376
1377 void
1378 on_papercolorGreen_activate            (GtkMenuItem     *menuitem,
1379                                         gpointer         user_data)
1380 {
1381   end_text();
1382   process_papercolor_activate(menuitem, COLOR_GREEN, predef_bgcolors_rgba[COLOR_GREEN]);
1383 }
1384
1385
1386 void
1387 on_papercolorOther_activate            (GtkMenuItem     *menuitem,
1388                                         gpointer         user_data)
1389 {
1390   GtkWidget *dialog;
1391   GtkColorSelection *colorsel;
1392   gint result;
1393   guint rgba;
1394   GdkColor gdkcolor;
1395   
1396   end_text();
1397   dialog = gtk_color_selection_dialog_new(_("Pick a Paper Color"));
1398   colorsel = GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(dialog)->colorsel);
1399   if (ui.cur_page->bg->type == BG_SOLID) rgba = ui.cur_page->bg->color_rgba;
1400   else rgba = ui.default_page.bg->color_rgba;
1401   rgb_to_gdkcolor(rgba, &gdkcolor);
1402   gtk_color_selection_set_current_color(colorsel, &gdkcolor);
1403   
1404   if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) {
1405     gtk_color_selection_get_current_color(colorsel, &gdkcolor);
1406     process_papercolor_activate(menuitem, COLOR_OTHER, gdkcolor_to_rgba(gdkcolor, 0xffff));
1407   }
1408   gtk_widget_destroy(dialog);
1409 }
1410
1411
1412 void
1413 on_paperstylePlain_activate            (GtkMenuItem     *menuitem,
1414                                         gpointer         user_data)
1415 {
1416   end_text();
1417   process_paperstyle_activate(menuitem, RULING_NONE);
1418 }
1419
1420
1421 void
1422 on_paperstyleLined_activate            (GtkMenuItem     *menuitem,
1423                                         gpointer         user_data)
1424 {
1425   end_text();
1426   process_paperstyle_activate(menuitem, RULING_LINED);
1427 }
1428
1429
1430 void
1431 on_paperstyleRuled_activate            (GtkMenuItem     *menuitem,
1432                                         gpointer         user_data)
1433 {
1434   end_text();
1435   process_paperstyle_activate(menuitem, RULING_RULED);
1436 }
1437
1438
1439 void
1440 on_paperstyleGraph_activate            (GtkMenuItem     *menuitem,
1441                                         gpointer         user_data)
1442 {
1443   end_text();
1444   process_paperstyle_activate(menuitem, RULING_GRAPH);
1445 }
1446
1447
1448 void
1449 on_journalLoadBackground_activate      (GtkMenuItem     *menuitem,
1450                                         gpointer         user_data)
1451 {
1452   GtkWidget *dialog, *attach_opt;
1453   struct Background *bg;
1454   struct Page *pg;
1455   int pageno;
1456   GList *bglist, *bglistiter;
1457   GtkFileFilter *filt_all, *filt_pix, *filt_pspdf;
1458   char *filename;
1459   gboolean attach;
1460   
1461   end_text();
1462   dialog = gtk_file_chooser_dialog_new(_("Open Background"), GTK_WINDOW (winMain),
1463      GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1464      GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
1465 #ifdef FILE_DIALOG_SIZE_BUGFIX
1466   gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
1467 #endif
1468
1469   filt_all = gtk_file_filter_new();
1470   gtk_file_filter_set_name(filt_all, _("All files"));
1471   gtk_file_filter_add_pattern(filt_all, "*");
1472   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
1473
1474 #if GTK_CHECK_VERSION(2,6,0)
1475
1476   if (!gtk_check_version(2, 6, 0)) {
1477     filt_pix = gtk_file_filter_new();
1478     gtk_file_filter_set_name(filt_pix, _("Bitmap files"));
1479     gtk_file_filter_add_pixbuf_formats(filt_pix);
1480     gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pix);
1481   }
1482   
1483 #endif
1484
1485   filt_pspdf = gtk_file_filter_new();
1486   gtk_file_filter_set_name(filt_pspdf, _("PS/PDF files (as bitmaps)"));
1487   gtk_file_filter_add_pattern(filt_pspdf, "*.ps");
1488   gtk_file_filter_add_pattern(filt_pspdf, "*.PS");
1489   gtk_file_filter_add_pattern(filt_pspdf, "*.pdf");
1490   gtk_file_filter_add_pattern(filt_pspdf, "*.PDF");
1491   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pspdf);
1492
1493   attach_opt = gtk_check_button_new_with_label(_("Attach file to the journal"));
1494   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(attach_opt), FALSE);
1495   gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER (dialog), attach_opt);
1496
1497   if (ui.default_path!=NULL) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
1498   
1499   if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
1500     gtk_widget_destroy(dialog);
1501     return;
1502   }
1503   filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1504   attach = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(attach_opt));
1505   gtk_widget_destroy(dialog);
1506   
1507   set_cursor_busy(TRUE);
1508   bg = attempt_load_pix_bg(filename, attach);
1509   if (bg != NULL) bglist = g_list_append(NULL, bg);
1510   else bglist = attempt_load_gv_bg(filename);
1511   set_cursor_busy(FALSE);
1512   
1513   if (bglist == NULL) {
1514     dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL,
1515       GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
1516       _("Error opening background '%s'"), filename);
1517     gtk_dialog_run(GTK_DIALOG(dialog));
1518     gtk_widget_destroy(dialog);
1519     g_free(filename);
1520     return;
1521   }
1522
1523   g_free(filename);
1524   reset_selection();
1525   pageno = ui.pageno;
1526
1527   for (bglistiter = bglist, pageno = ui.pageno; 
1528            bglistiter!=NULL; bglistiter = bglistiter->next, pageno++) {
1529     prepare_new_undo();
1530     if (bglistiter->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
1531     if (bglistiter->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
1532
1533     bg = (struct Background *)bglistiter->data;
1534     
1535     if (pageno == journal.npages) {
1536       undo->type = ITEM_NEW_PAGE;
1537       pg = new_page_with_bg(bg, 
1538               gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale,
1539               gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale);
1540       journal.pages = g_list_append(journal.pages, pg);
1541       journal.npages++;
1542       undo->val = pageno;
1543       undo->page = pg;
1544     } else
1545     {
1546       pg = g_list_nth_data(journal.pages, pageno);
1547       undo->type = ITEM_NEW_BG_RESIZE;
1548       undo->page = pg;
1549       undo->bg = pg->bg;
1550       bg->canvas_item = undo->bg->canvas_item;
1551       undo->bg->canvas_item = NULL;
1552       undo->val_x = pg->width;
1553       undo->val_y = pg->height;
1554       pg->bg = bg;
1555       pg->width = gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale;
1556       pg->height = gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale;
1557       make_page_clipbox(pg);
1558       update_canvas_bg(pg);
1559     }
1560   }
1561
1562   g_list_free(bglist);
1563   if (ui.zoom != DEFAULT_ZOOM) {
1564     ui.zoom = DEFAULT_ZOOM;
1565     gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
1566     rescale_text_items();
1567     rescale_bg_pixmaps();
1568     rescale_images();
1569   }
1570   do_switch_page(ui.pageno, TRUE, TRUE);
1571 }
1572
1573 void
1574 on_journalScreenshot_activate          (GtkMenuItem     *menuitem,
1575                                         gpointer         user_data)
1576 {
1577   struct Background *bg;
1578   
1579   end_text();
1580   reset_selection();
1581   gtk_window_iconify(GTK_WINDOW(winMain)); // hide ourselves
1582   gdk_display_sync(gdk_display_get_default());
1583
1584   if (ui.cursor!=NULL)
1585     gdk_cursor_unref(ui.cursor);
1586   ui.cursor = gdk_cursor_new(GDK_TCROSS);
1587
1588   bg = attempt_screenshot_bg();
1589     
1590   gtk_window_deiconify(GTK_WINDOW(winMain));
1591   update_cursor();
1592   if (bg==NULL) return;
1593
1594   prepare_new_undo();
1595   undo->type = ITEM_NEW_BG_RESIZE;
1596   undo->page = ui.cur_page;
1597   undo->bg = ui.cur_page->bg;
1598   bg->canvas_item = undo->bg->canvas_item;
1599   undo->bg->canvas_item = NULL;
1600   undo->val_x = ui.cur_page->width;
1601   undo->val_y = ui.cur_page->height;
1602
1603   ui.cur_page->bg = bg;
1604   ui.cur_page->width = gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale;
1605   ui.cur_page->height = gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale;
1606
1607   make_page_clipbox(ui.cur_page);
1608   update_canvas_bg(ui.cur_page);
1609
1610   if (ui.zoom != DEFAULT_ZOOM) {
1611     ui.zoom = DEFAULT_ZOOM;
1612     gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
1613     rescale_text_items();
1614     rescale_bg_pixmaps();
1615     rescale_images();
1616   }
1617   do_switch_page(ui.pageno, TRUE, TRUE);
1618 }
1619
1620
1621 void
1622 on_journalApplyAllPages_activate       (GtkMenuItem     *menuitem,
1623                                         gpointer         user_data)
1624 {
1625   gboolean active;
1626   
1627   end_text();
1628   active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
1629   if (active == ui.bg_apply_all_pages) return;
1630   ui.bg_apply_all_pages = active;
1631   update_page_stuff();
1632   
1633 /* THIS IS THE OLD VERSION OF THE FEATURE -- APPLIED CURRENT BG TO ALL
1634   struct Page *page;
1635   GList *pglist;
1636   
1637   if (ui.cur_page->bg->type != BG_SOLID) return;
1638   reset_selection();
1639   for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
1640     page = (struct Page *)pglist->data;
1641     prepare_new_undo();
1642     undo->type = ITEM_NEW_BG_RESIZE;
1643     undo->page = page;
1644     undo->bg = page->bg;
1645     undo->val_x = page->width;
1646     undo->val_y = page->height; 
1647     if (pglist->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
1648     if (pglist->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
1649     page->bg = (struct Background *)g_memdup(ui.cur_page->bg, sizeof(struct Background));
1650     page->width = ui.cur_page->width;
1651     page->height = ui.cur_page->height;
1652     page->bg->canvas_item = undo->bg->canvas_item;
1653     undo->bg->canvas_item = NULL;
1654   
1655     make_page_clipbox(page);
1656     update_canvas_bg(page);
1657   }
1658   do_switch_page(ui.pageno, TRUE, TRUE);
1659 */
1660
1661 }
1662
1663
1664 void
1665 on_toolsPen_activate                   (GtkMenuItem     *menuitem,
1666                                         gpointer         user_data)
1667 {
1668   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1669     if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1670       return;
1671   } else {
1672     if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1673       return;
1674   }
1675   
1676   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1677   if (ui.toolno[ui.cur_mapping] == TOOL_PEN) return;
1678
1679   ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1680   end_text();
1681   reset_selection();
1682   ui.toolno[ui.cur_mapping] = TOOL_PEN;
1683   ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
1684   ui.cur_brush->ruler = ui.default_brushes[TOOL_PEN].ruler;
1685   ui.cur_brush->recognizer = ui.default_brushes[TOOL_PEN].recognizer;
1686   update_mapping_linkings(TOOL_PEN);
1687   update_tool_buttons();
1688   update_tool_menu();
1689   update_color_menu();
1690   update_cursor();
1691 }
1692
1693
1694 void
1695 on_toolsEraser_activate                (GtkMenuItem     *menuitem,
1696                                         gpointer         user_data)
1697 {
1698   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1699     if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1700       return;
1701   } else {
1702     if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1703       return;
1704   }
1705   
1706   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1707   if (ui.toolno[ui.cur_mapping] == TOOL_ERASER) return;
1708   
1709   ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1710   end_text();
1711   reset_selection();
1712   ui.toolno[ui.cur_mapping] = TOOL_ERASER;
1713   ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_ERASER]);
1714   update_mapping_linkings(TOOL_ERASER);
1715   update_tool_buttons();
1716   update_tool_menu();
1717   update_color_menu();
1718   update_cursor();
1719 }
1720
1721
1722 void
1723 on_toolsHighlighter_activate           (GtkMenuItem     *menuitem,
1724                                         gpointer         user_data)
1725 {
1726   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1727     if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1728       return;
1729   } else {
1730     if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1731       return;
1732   }
1733   
1734   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1735   if (ui.toolno[ui.cur_mapping] == TOOL_HIGHLIGHTER) return;
1736   
1737   ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1738   end_text();
1739   reset_selection();
1740   ui.toolno[ui.cur_mapping] = TOOL_HIGHLIGHTER;
1741   ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_HIGHLIGHTER]);
1742   ui.cur_brush->ruler = ui.default_brushes[TOOL_HIGHLIGHTER].ruler;
1743   ui.cur_brush->recognizer = ui.default_brushes[TOOL_HIGHLIGHTER].recognizer;
1744   update_mapping_linkings(TOOL_HIGHLIGHTER);
1745   update_tool_buttons();
1746   update_tool_menu();
1747   update_color_menu();
1748   update_cursor();
1749 }
1750
1751
1752 void
1753 on_toolsText_activate                  (GtkMenuItem     *menuitem,
1754                                         gpointer         user_data)
1755 {
1756   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1757     if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1758       return;
1759   } else {
1760     if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1761       return;
1762   }
1763   
1764   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1765   if (ui.toolno[ui.cur_mapping] == TOOL_TEXT) return;
1766   
1767   ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1768   reset_selection();
1769   ui.toolno[ui.cur_mapping] = TOOL_TEXT;
1770   ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
1771   update_mapping_linkings(-1);
1772   update_tool_buttons();
1773   update_tool_menu();
1774   update_color_menu();
1775   update_cursor();
1776 }
1777
1778
1779 void
1780 on_toolsImage_activate                 (GtkMenuItem *menuitem,
1781                                         gpointer         user_data)
1782 {
1783   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1784     if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1785       return;
1786   } else {
1787     if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1788       return;
1789   }
1790   
1791   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1792   if (ui.toolno[ui.cur_mapping] == TOOL_IMAGE) return;
1793   
1794   ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1795   end_text();
1796   reset_selection();
1797   ui.toolno[ui.cur_mapping] = TOOL_IMAGE;
1798   update_mapping_linkings(-1);
1799   update_tool_buttons();
1800   update_tool_menu();
1801   update_color_menu();
1802   update_cursor();
1803 }
1804
1805
1806 void
1807 on_toolsSelectRegion_activate          (GtkMenuItem     *menuitem,
1808                                         gpointer         user_data)
1809 {
1810
1811 }
1812
1813
1814 void
1815 on_toolsSelectRectangle_activate       (GtkMenuItem     *menuitem,
1816                                         gpointer         user_data)
1817 {
1818   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1819     if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1820       return;
1821   } else {
1822     if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1823       return;
1824   }
1825   
1826   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1827   if (ui.toolno[ui.cur_mapping] == TOOL_SELECTRECT) return;
1828   
1829   ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1830   end_text();
1831   ui.toolno[ui.cur_mapping] = TOOL_SELECTRECT;
1832   update_mapping_linkings(-1);
1833   update_tool_buttons();
1834   update_tool_menu();
1835   update_color_menu();
1836   update_cursor();
1837 }
1838
1839
1840 void
1841 on_toolsVerticalSpace_activate         (GtkMenuItem     *menuitem,
1842                                         gpointer         user_data)
1843 {
1844   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1845     if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1846       return;
1847   } else {
1848     if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1849       return;
1850   }
1851   
1852   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1853   if (ui.toolno[ui.cur_mapping] == TOOL_VERTSPACE) return;
1854   
1855   ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1856   end_text();
1857   reset_selection();
1858   ui.toolno[ui.cur_mapping] = TOOL_VERTSPACE;
1859   update_mapping_linkings(-1);
1860   update_tool_buttons();
1861   update_tool_menu();
1862   update_color_menu();
1863   update_cursor();
1864 }
1865
1866
1867 void
1868 on_colorBlack_activate                 (GtkMenuItem     *menuitem,
1869                                         gpointer         user_data)
1870 {
1871   process_color_activate(menuitem, COLOR_BLACK, predef_colors_rgba[COLOR_BLACK]);
1872 }
1873
1874
1875 void
1876 on_colorBlue_activate                  (GtkMenuItem     *menuitem,
1877                                         gpointer         user_data)
1878 {
1879   process_color_activate(menuitem, COLOR_BLUE, predef_colors_rgba[COLOR_BLUE]);
1880 }
1881
1882
1883 void
1884 on_colorRed_activate                   (GtkMenuItem     *menuitem,
1885                                         gpointer         user_data)
1886 {
1887   process_color_activate(menuitem, COLOR_RED, predef_colors_rgba[COLOR_RED]);
1888 }
1889
1890
1891 void
1892 on_colorGreen_activate                 (GtkMenuItem     *menuitem,
1893                                         gpointer         user_data)
1894 {
1895   process_color_activate(menuitem, COLOR_GREEN, predef_colors_rgba[COLOR_GREEN]);
1896 }
1897
1898
1899 void
1900 on_colorGray_activate                  (GtkMenuItem     *menuitem,
1901                                         gpointer         user_data)
1902 {
1903   process_color_activate(menuitem, COLOR_GRAY, predef_colors_rgba[COLOR_GRAY]);
1904 }
1905
1906
1907 void
1908 on_colorLightBlue_activate             (GtkMenuItem     *menuitem,
1909                                         gpointer         user_data)
1910 {
1911   process_color_activate(menuitem, COLOR_LIGHTBLUE, predef_colors_rgba[COLOR_LIGHTBLUE]);
1912 }
1913
1914
1915 void
1916 on_colorLightGreen_activate            (GtkMenuItem     *menuitem,
1917                                         gpointer         user_data)
1918 {
1919   process_color_activate(menuitem, COLOR_LIGHTGREEN, predef_colors_rgba[COLOR_LIGHTGREEN]);
1920 }
1921
1922
1923 void
1924 on_colorMagenta_activate               (GtkMenuItem     *menuitem,
1925                                         gpointer         user_data)
1926 {
1927   process_color_activate(menuitem, COLOR_MAGENTA, predef_colors_rgba[COLOR_MAGENTA]);
1928 }
1929
1930
1931 void
1932 on_colorOrange_activate                (GtkMenuItem     *menuitem,
1933                                         gpointer         user_data)
1934 {
1935   process_color_activate(menuitem, COLOR_ORANGE, predef_colors_rgba[COLOR_ORANGE]);
1936 }
1937
1938
1939 void
1940 on_colorYellow_activate                (GtkMenuItem     *menuitem,
1941                                         gpointer         user_data)
1942 {
1943   process_color_activate(menuitem, COLOR_YELLOW, predef_colors_rgba[COLOR_YELLOW]);
1944 }
1945
1946
1947 void
1948 on_colorWhite_activate                 (GtkMenuItem     *menuitem,
1949                                         gpointer         user_data)
1950 {
1951   process_color_activate(menuitem, COLOR_WHITE, predef_colors_rgba[COLOR_WHITE]);
1952 }
1953
1954
1955 void
1956 on_colorOther_activate                 (GtkMenuItem     *menuitem,
1957                                         gpointer         user_data)
1958 {
1959   gtk_button_clicked(GTK_BUTTON(GET_COMPONENT("buttonColorChooser")));
1960 }
1961
1962
1963 void
1964 on_penthicknessVeryFine_activate       (GtkMenuItem     *menuitem,
1965                                         gpointer         user_data)
1966 {
1967   process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_VERYFINE);
1968 }
1969
1970
1971 void
1972 on_penthicknessFine_activate           (GtkMenuItem     *menuitem,
1973                                         gpointer         user_data)
1974 {
1975   process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_FINE);
1976 }
1977
1978
1979 void
1980 on_penthicknessMedium_activate         (GtkMenuItem     *menuitem,
1981                                         gpointer         user_data)
1982 {
1983   process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_MEDIUM);
1984 }
1985
1986
1987 void
1988 on_penthicknessThick_activate          (GtkMenuItem     *menuitem,
1989                                         gpointer         user_data)
1990 {
1991   process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_THICK);
1992 }
1993
1994
1995 void
1996 on_penthicknessVeryThick_activate      (GtkMenuItem     *menuitem,
1997                                         gpointer         user_data)
1998 {
1999   process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_VERYTHICK);
2000 }
2001
2002
2003 void
2004 on_eraserFine_activate                 (GtkMenuItem     *menuitem,
2005                                         gpointer         user_data)
2006 {
2007   process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_FINE);
2008 }
2009
2010
2011 void
2012 on_eraserMedium_activate               (GtkMenuItem     *menuitem,
2013                                         gpointer         user_data)
2014 {
2015   process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_MEDIUM);
2016 }
2017
2018
2019 void
2020 on_eraserThick_activate                (GtkMenuItem     *menuitem,
2021                                         gpointer         user_data)
2022 {
2023   process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_THICK);
2024 }
2025
2026
2027 void
2028 on_eraserStandard_activate             (GtkMenuItem     *menuitem,
2029                                         gpointer         user_data)
2030 {
2031   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
2032   end_text();
2033   ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_STANDARD;
2034   update_mapping_linkings(TOOL_ERASER);
2035 }
2036
2037
2038 void
2039 on_eraserWhiteout_activate             (GtkMenuItem     *menuitem,
2040                                         gpointer         user_data)
2041 {
2042   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
2043   end_text();
2044   ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_WHITEOUT;
2045   update_mapping_linkings(TOOL_ERASER);
2046 }
2047
2048
2049 void
2050 on_eraserDeleteStrokes_activate        (GtkMenuItem     *menuitem,
2051                                         gpointer         user_data)
2052 {
2053   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
2054   end_text();
2055   ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_STROKES;
2056   update_mapping_linkings(TOOL_ERASER);
2057 }
2058
2059
2060 void
2061 on_highlighterFine_activate            (GtkMenuItem     *menuitem,
2062                                         gpointer         user_data)
2063 {
2064   process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_FINE);
2065 }
2066
2067
2068 void
2069 on_highlighterMedium_activate          (GtkMenuItem     *menuitem,
2070                                         gpointer         user_data)
2071 {
2072   process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_MEDIUM);
2073 }
2074
2075
2076 void
2077 on_highlighterThick_activate           (GtkMenuItem     *menuitem,
2078                                         gpointer         user_data)
2079 {
2080   process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_THICK);
2081 }
2082
2083
2084 void
2085 on_toolsTextFont_activate              (GtkMenuItem     *menuitem,
2086                                         gpointer         user_data)
2087 {
2088   GtkWidget *dialog;
2089   gchar *str;
2090   
2091   dialog = gtk_font_selection_dialog_new(_("Select Font"));
2092   str = make_cur_font_name();
2093   gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dialog), str);
2094   g_free(str);
2095   if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
2096     gtk_widget_destroy(dialog);
2097     return;
2098   }
2099   str = gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(dialog));
2100   gtk_widget_destroy(dialog);
2101   process_font_sel(str);
2102 }    
2103
2104 void
2105 on_toolsDefaultPen_activate            (GtkMenuItem     *menuitem,
2106                                         gpointer         user_data)
2107 {
2108   switch_mapping(0);
2109   end_text();
2110   reset_selection();
2111   g_memmove(&(ui.brushes[0][TOOL_PEN]), ui.default_brushes+TOOL_PEN, sizeof(struct Brush));
2112   ui.toolno[0] = TOOL_PEN;
2113   ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
2114   update_mapping_linkings(TOOL_PEN);
2115   update_tool_buttons();
2116   update_tool_menu();
2117   update_pen_props_menu();
2118   update_color_menu();
2119   update_cursor();
2120 }
2121
2122
2123 void
2124 on_toolsDefaultEraser_activate         (GtkMenuItem     *menuitem,
2125                                         gpointer         user_data)
2126 {
2127   switch_mapping(0);
2128   end_text();
2129   reset_selection();
2130   g_memmove(&(ui.brushes[0][TOOL_ERASER]), ui.default_brushes+TOOL_ERASER, sizeof(struct Brush));
2131   ui.toolno[0] = TOOL_ERASER;
2132   ui.cur_brush = &(ui.brushes[0][TOOL_ERASER]);
2133   update_mapping_linkings(TOOL_ERASER);
2134   update_tool_buttons();
2135   update_tool_menu();
2136   update_eraser_props_menu();
2137   update_color_menu();
2138   update_cursor();
2139 }
2140
2141
2142 void
2143 on_toolsDefaultHighlighter_activate    (GtkMenuItem     *menuitem,
2144                                         gpointer         user_data)
2145 {
2146   switch_mapping(0);
2147   end_text();
2148   reset_selection();
2149   g_memmove(&(ui.brushes[0][TOOL_HIGHLIGHTER]), ui.default_brushes+TOOL_HIGHLIGHTER, sizeof(struct Brush));
2150   ui.toolno[0] = TOOL_HIGHLIGHTER;
2151   ui.cur_brush = &(ui.brushes[0][TOOL_HIGHLIGHTER]);
2152   update_mapping_linkings(TOOL_HIGHLIGHTER);
2153   update_tool_buttons();
2154   update_tool_menu();
2155   update_highlighter_props_menu();
2156   update_color_menu();
2157   update_cursor();
2158 }
2159
2160 void
2161 on_toolsDefaultText_activate           (GtkMenuItem     *menuitem,
2162                                         gpointer         user_data)
2163 {
2164   switch_mapping(0);
2165   if (ui.toolno[0]!=TOOL_TEXT) end_text();
2166   reset_selection();
2167   ui.toolno[0] = TOOL_TEXT;
2168   ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
2169   ui.cur_brush->color_no = ui.default_brushes[TOOL_PEN].color_no;
2170   ui.cur_brush->color_rgba = ui.default_brushes[TOOL_PEN].color_rgba;
2171   g_free(ui.font_name);
2172   ui.font_name = g_strdup(ui.default_font_name);
2173   ui.font_size = ui.default_font_size;
2174   if (ui.cur_item_type == ITEM_TEXT) {
2175     refont_text_item(ui.cur_item, ui.font_name, ui.font_size);
2176   }
2177   update_font_button();
2178   update_mapping_linkings(-1);
2179   update_tool_buttons();
2180   update_tool_menu();
2181   update_color_menu();
2182   update_cursor();
2183 }
2184
2185
2186 void
2187 on_toolsSetAsDefault_activate          (GtkMenuItem     *menuitem,
2188                                         gpointer         user_data)
2189 {
2190   struct Item *it;
2191   
2192   if (ui.cur_mapping!=0 && !ui.button_switch_mapping) return;
2193   if (ui.toolno[ui.cur_mapping] < NUM_STROKE_TOOLS)
2194     g_memmove(ui.default_brushes+ui.toolno[ui.cur_mapping], 
2195               &(ui.brushes[ui.cur_mapping][ui.toolno[ui.cur_mapping]]), sizeof(struct Brush));
2196   if (ui.toolno[ui.cur_mapping] == TOOL_TEXT) {
2197     if (ui.cur_item_type == ITEM_TEXT) {
2198       g_free(ui.font_name);
2199       ui.font_name = g_strdup(ui.cur_item->font_name);
2200       ui.font_size = ui.cur_item->font_size;
2201     }
2202     else if (ui.selection!=NULL && ui.selection->items!=NULL &&
2203              ui.selection->items->next==NULL &&
2204              (it=(struct Item*)ui.selection->items->data)->type == ITEM_TEXT) {
2205       g_free(ui.font_name);
2206       ui.font_name = g_strdup(it->font_name);
2207       ui.font_size = it->font_size;
2208     }
2209     g_free(ui.default_font_name);
2210     ui.default_font_name = g_strdup(ui.font_name);
2211     ui.default_font_size = ui.font_size;
2212   }
2213   end_text();
2214 }
2215
2216
2217 void
2218 on_toolsRuler_activate                 (GtkMenuItem     *menuitem,
2219                                         gpointer         user_data)
2220 {
2221   gboolean active, current;
2222   
2223   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
2224     active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2225   else
2226     active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
2227
2228   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2229   current = (ui.toolno[ui.cur_mapping] == TOOL_PEN || ui.toolno[ui.cur_mapping] == TOOL_HIGHLIGHTER) && ui.cur_brush->ruler;
2230   if (active == current) return;
2231
2232   ui.cur_mapping = 0;  
2233   end_text();
2234   if (ui.toolno[ui.cur_mapping]!=TOOL_PEN && ui.toolno[ui.cur_mapping]!=TOOL_HIGHLIGHTER) {
2235     reset_selection();
2236     ui.toolno[ui.cur_mapping] = TOOL_PEN;
2237     ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
2238     update_color_menu();
2239     update_tool_buttons();
2240     update_tool_menu();
2241     update_cursor();
2242   }
2243   
2244   ui.cur_brush->ruler = active;
2245   if (active) ui.cur_brush->recognizer = FALSE;
2246   update_mapping_linkings(ui.toolno[ui.cur_mapping]);
2247   update_ruler_indicator();
2248 }
2249
2250
2251 void
2252 on_toolsReco_activate                  (GtkMenuItem *menuitem,
2253                                         gpointer         user_data)
2254 {
2255   gboolean active, current;
2256   
2257   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
2258     active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2259   else
2260     active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
2261
2262   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2263   current = (ui.toolno[ui.cur_mapping] == TOOL_PEN || ui.toolno[ui.cur_mapping] == TOOL_HIGHLIGHTER) && ui.cur_brush->recognizer;
2264   if (active == current) return;
2265   
2266   ui.cur_mapping = 0;
2267   end_text();
2268   if (ui.toolno[ui.cur_mapping]!=TOOL_PEN && ui.toolno[ui.cur_mapping]!=TOOL_HIGHLIGHTER) {
2269     reset_selection();
2270     ui.toolno[ui.cur_mapping] = TOOL_PEN;
2271     ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
2272     update_color_menu();
2273     update_tool_buttons();
2274     update_tool_menu();
2275     update_cursor();
2276   }
2277   
2278   ui.cur_brush->recognizer = active;
2279   if (active) {
2280     ui.cur_brush->ruler = FALSE;
2281     reset_recognizer();
2282   }
2283   update_mapping_linkings(ui.toolno[ui.cur_mapping]);
2284   update_ruler_indicator();
2285 }
2286
2287
2288 void
2289 on_optionsSavePreferences_activate     (GtkMenuItem     *menuitem,
2290                                         gpointer         user_data)
2291 {
2292   end_text();
2293   save_config_to_file();
2294 }
2295
2296
2297 void
2298 on_helpIndex_activate                  (GtkMenuItem     *menuitem,
2299                                         gpointer         user_data)
2300 {
2301
2302 }
2303
2304
2305 void
2306 on_helpAbout_activate                  (GtkMenuItem     *menuitem,
2307                                         gpointer         user_data)
2308 {
2309   GtkWidget *aboutDialog;
2310   GtkLabel *labelTitle;
2311   
2312   end_text();
2313   aboutDialog = create_aboutDialog ();
2314   labelTitle = GTK_LABEL(g_object_get_data(G_OBJECT(aboutDialog), "labelTitle"));
2315   gtk_label_set_markup(labelTitle, 
2316     "<span size=\"xx-large\" weight=\"bold\">Xournal " VERSION_STRING "</span>");
2317   gtk_dialog_run (GTK_DIALOG(aboutDialog));
2318   gtk_widget_destroy(aboutDialog);
2319 }
2320
2321
2322 void
2323 on_buttonToolDefault_clicked           (GtkToolButton   *toolbutton,
2324                                         gpointer         user_data)
2325 {
2326   if (ui.toolno[0]==TOOL_TEXT) {
2327     on_toolsDefaultText_activate(NULL, NULL);
2328     return;
2329   }
2330   end_text();
2331   switch_mapping(0);
2332   if (ui.toolno[0] < NUM_STROKE_TOOLS) {
2333     g_memmove(&(ui.brushes[0][ui.toolno[0]]), ui.default_brushes+ui.toolno[0], sizeof(struct Brush));
2334     update_mapping_linkings(ui.toolno[0]);
2335     update_thickness_buttons();
2336     update_color_buttons();
2337     update_color_menu();
2338     if (ui.toolno[0] == TOOL_PEN) update_pen_props_menu();
2339     if (ui.toolno[0] == TOOL_ERASER) update_eraser_props_menu();
2340     if (ui.toolno[0] == TOOL_HIGHLIGHTER) update_highlighter_props_menu();
2341     update_cursor();
2342   }
2343 }
2344
2345
2346 void
2347 on_buttonFine_clicked                  (GtkToolButton   *toolbutton,
2348                                         gpointer         user_data)
2349 {
2350   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2351   process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[ui.cur_mapping], THICKNESS_FINE);
2352 }
2353
2354
2355 void
2356 on_buttonMedium_clicked                (GtkToolButton   *toolbutton,
2357                                         gpointer         user_data)
2358 {
2359   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2360   process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[ui.cur_mapping], THICKNESS_MEDIUM);
2361 }
2362
2363
2364 void
2365 on_buttonThick_clicked                 (GtkToolButton   *toolbutton,
2366                                         gpointer         user_data)
2367 {
2368   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2369   process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[ui.cur_mapping], THICKNESS_THICK);
2370 }
2371
2372
2373 gboolean
2374 on_canvas_button_press_event           (GtkWidget       *widget,
2375                                         GdkEventButton  *event,
2376                                         gpointer         user_data)
2377 {
2378   double pt[2];
2379   GtkWidget *dialog;
2380   int mapping;
2381   gboolean is_core;
2382   struct Item *item;
2383   GdkEvent scroll_event;
2384
2385 #ifdef INPUT_DEBUG
2386   printf("DEBUG: ButtonPress (%s) (x,y)=(%.2f,%.2f), button %d, modifier %x\n", 
2387     event->device->name, event->x, event->y, event->button, event->state);
2388 #endif
2389
2390   // abort any page changes pending in the spin button, and take the focus
2391   gtk_spin_button_set_value(GTK_SPIN_BUTTON(GET_COMPONENT("spinPageNo")), ui.pageno+1);
2392   reset_focus();
2393     
2394   is_core = (event->device == gdk_device_get_core_pointer());
2395   if (!ui.use_xinput && !is_core) return FALSE;
2396   if (ui.use_xinput && is_core && ui.discard_corepointer) return FALSE;
2397   if (event->type != GDK_BUTTON_PRESS) return FALSE; 
2398     // double-clicks may have broken axes member (free'd) due to a bug in GDK
2399
2400   if (event->button > 3) { // scroll wheel events! don't paint...
2401     if (ui.use_xinput && !gtk_check_version(2, 17, 0) && event->button <= 7) {
2402       /* with GTK+ 2.17 and later, the entire widget hierarchy is xinput-aware,
2403          so the core button event gets discarded and the scroll event never 
2404          gets processed by the main window. This is arguably a GTK+ bug.
2405          We work around it. */
2406       scroll_event.scroll.type = GDK_SCROLL;
2407       scroll_event.scroll.window = event->window;
2408       scroll_event.scroll.send_event = event->send_event;
2409       scroll_event.scroll.time = event->time;
2410       scroll_event.scroll.x = event->x;
2411       scroll_event.scroll.y = event->y;
2412       scroll_event.scroll.state = event->state;
2413       scroll_event.scroll.device = event->device;
2414       scroll_event.scroll.x_root = event->x_root;
2415       scroll_event.scroll.y_root = event->y_root;
2416       if (event->button == 4) scroll_event.scroll.direction = GDK_SCROLL_UP;
2417       else if (event->button == 5) scroll_event.scroll.direction = GDK_SCROLL_DOWN;
2418       else if (event->button == 6) scroll_event.scroll.direction = GDK_SCROLL_LEFT;
2419       else scroll_event.scroll.direction = GDK_SCROLL_RIGHT;
2420       gtk_widget_event(GET_COMPONENT("scrolledwindowMain"), &scroll_event);
2421     }
2422     return FALSE;
2423   }
2424   if ((event->state & (GDK_CONTROL_MASK|GDK_MOD1_MASK)) != 0) return FALSE;
2425     // no control-clicking or alt-clicking
2426   if (!is_core) gdk_device_get_state(event->device, event->window, event->axes, NULL);
2427     // synaptics touchpads send bogus axis values with ButtonDown
2428   if (!is_core)
2429     fix_xinput_coords((GdkEvent *)event);
2430
2431   if (!finite_sized(event->x) || !finite_sized(event->y)) return FALSE; // Xorg 7.3 bug
2432
2433   if (ui.cur_item_type == ITEM_TEXT) {
2434     if (!is_event_within_textview(event)) end_text();
2435     else return FALSE;
2436   }
2437   if (ui.cur_item_type == ITEM_STROKE && ui.is_corestroke && !is_core &&
2438       ui.cur_path.num_points == 1) { 
2439       // Xorg 7.3+ sent core event before XInput event: fix initial point 
2440     ui.is_corestroke = FALSE;
2441     get_pointer_coords((GdkEvent *)event, ui.cur_path.coords);
2442   }
2443   if (ui.cur_item_type != ITEM_NONE) return FALSE; // we're already doing something
2444
2445   // if button_switch_mapping enabled, button 2 or 3 clicks only switch mapping
2446   if (ui.button_switch_mapping && event->button > 1) {
2447     ui.which_unswitch_button = event->button;
2448     switch_mapping(event->button-1);
2449     return FALSE;
2450   }
2451
2452   ui.is_corestroke = is_core;
2453   ui.stroke_device = event->device;
2454
2455   if (ui.use_erasertip && event->device->source == GDK_SOURCE_ERASER)
2456     mapping = NUM_BUTTONS;
2457   else if (ui.button_switch_mapping) {
2458     mapping = ui.cur_mapping;
2459     if (!mapping && (event->state & GDK_BUTTON2_MASK)) mapping = 1;
2460     if (!mapping && (event->state & GDK_BUTTON3_MASK)) mapping = 2;
2461   }
2462   else mapping = event->button-1;
2463
2464   // check whether we're in a page
2465   get_pointer_coords((GdkEvent *)event, pt);
2466   set_current_page(pt);
2467   
2468   // can't paint on the background...
2469
2470   if (ui.cur_layer == NULL) {
2471     /* warn */
2472     dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL,
2473       GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("Drawing is not allowed on the "
2474       "background layer.\n Switching to Layer 1."));
2475     gtk_dialog_run(GTK_DIALOG(dialog));
2476     gtk_widget_destroy(dialog);
2477     on_viewShowLayer_activate(NULL, NULL);
2478     return FALSE;
2479   }
2480
2481   // switch mappings if needed
2482   
2483   ui.which_mouse_button = event->button;
2484   switch_mapping(mapping);
2485 #ifdef WIN32
2486   update_cursor();
2487 #endif
2488
2489   // in text tool, clicking in a text area edits it
2490   if (ui.toolno[mapping] == TOOL_TEXT) {
2491     item = click_is_in_text(ui.cur_layer, pt[0], pt[1]);
2492     if (item!=NULL) { 
2493       reset_selection();
2494       start_text((GdkEvent *)event, item);
2495       return FALSE;
2496     }
2497   }
2498
2499   // if this can be a selection move or resize, then it takes precedence over anything else  
2500   if (start_resizesel((GdkEvent *)event)) return FALSE;
2501   if (start_movesel((GdkEvent *)event)) return FALSE;
2502   
2503   if (ui.toolno[mapping] != TOOL_SELECTREGION && ui.toolno[mapping] != TOOL_SELECTRECT)
2504     reset_selection();
2505
2506   // process the event
2507   
2508   if (ui.toolno[mapping] == TOOL_HAND) {
2509     ui.cur_item_type = ITEM_HAND;
2510     get_pointer_coords((GdkEvent *)event, ui.hand_refpt);
2511     ui.hand_refpt[0] += ui.cur_page->hoffset;
2512     ui.hand_refpt[1] += ui.cur_page->voffset;
2513   } 
2514   else if (ui.toolno[mapping] == TOOL_PEN || ui.toolno[mapping] == TOOL_HIGHLIGHTER ||
2515         (ui.toolno[mapping] == TOOL_ERASER && ui.cur_brush->tool_options == TOOLOPT_ERASER_WHITEOUT)) {
2516     create_new_stroke((GdkEvent *)event);
2517   } 
2518   else if (ui.toolno[mapping] == TOOL_ERASER) {
2519     ui.cur_item_type = ITEM_ERASURE;
2520     do_eraser((GdkEvent *)event, ui.cur_brush->thickness/2,
2521                ui.cur_brush->tool_options == TOOLOPT_ERASER_STROKES);
2522   }
2523   else if (ui.toolno[mapping] == TOOL_SELECTRECT) {
2524     start_selectrect((GdkEvent *)event);
2525   }
2526   else if (ui.toolno[mapping] == TOOL_VERTSPACE) {
2527     start_vertspace((GdkEvent *)event);
2528   }
2529   else if (ui.toolno[mapping] == TOOL_TEXT) {
2530     start_text((GdkEvent *)event, NULL);
2531   }
2532   else if (ui.toolno[mapping] == TOOL_IMAGE) {
2533     insert_image((GdkEvent *)event);
2534   }
2535   return FALSE;
2536 }
2537
2538
2539 gboolean
2540 on_canvas_button_release_event         (GtkWidget       *widget,
2541                                         GdkEventButton  *event,
2542                                         gpointer         user_data)
2543 {
2544   gboolean is_core;
2545   
2546 #ifdef INPUT_DEBUG
2547   printf("DEBUG: ButtonRelease (%s) (x,y)=(%.2f,%.2f), button %d, modifier %x\n", 
2548       event->device->name, event->x, event->y, event->button, event->state);
2549 #endif
2550
2551   is_core = (event->device == gdk_device_get_core_pointer());
2552   if (!ui.use_xinput && !is_core) return FALSE;
2553   if (ui.use_xinput && is_core && !ui.is_corestroke) return FALSE;
2554   if (!is_core) fix_xinput_coords((GdkEvent *)event);
2555
2556   if (event->button != ui.which_mouse_button && 
2557       event->button != ui.which_unswitch_button)
2558     return FALSE;
2559
2560   if (ui.cur_item_type == ITEM_STROKE) {
2561     finalize_stroke();
2562     if (ui.cur_brush->recognizer) recognize_patterns();
2563   }
2564   else if (ui.cur_item_type == ITEM_ERASURE) {
2565     finalize_erasure();
2566   }
2567   else if (ui.cur_item_type == ITEM_SELECTRECT) {
2568     finalize_selectrect();
2569   }
2570   else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2571     finalize_movesel();
2572   }
2573   else if (ui.cur_item_type == ITEM_RESIZESEL) {
2574     finalize_resizesel();
2575   }
2576   else if (ui.cur_item_type == ITEM_HAND) {
2577     ui.cur_item_type = ITEM_NONE;
2578   }
2579   
2580   if (!ui.which_unswitch_button || event->button == ui.which_unswitch_button)
2581     switch_mapping(0); // will reset ui.which_unswitch_button
2582
2583   return FALSE;
2584 }
2585
2586
2587 gboolean
2588 on_canvas_enter_notify_event           (GtkWidget       *widget,
2589                                         GdkEventCrossing *event,
2590                                         gpointer         user_data)
2591 {
2592   GList *dev_list;
2593   GdkDevice *dev;
2594
2595 #ifdef INPUT_DEBUG
2596   printf("DEBUG: enter notify\n");
2597 #endif
2598     /* re-enable input devices after they've been emergency-disabled
2599        by leave_notify */
2600   if (!gtk_check_version(2, 17, 0)) {
2601     gdk_flush();
2602     gdk_error_trap_push();
2603     for (dev_list = gdk_devices_list(); dev_list != NULL; dev_list = dev_list->next) {
2604       dev = GDK_DEVICE(dev_list->data);
2605       gdk_device_set_mode(dev, GDK_MODE_SCREEN);
2606     }
2607     ui.is_corestroke = ui.saved_is_corestroke;
2608     gdk_flush();
2609     gdk_error_trap_pop();
2610   }
2611   return FALSE;
2612 }
2613
2614 gboolean
2615 on_canvas_leave_notify_event           (GtkWidget       *widget,
2616                                         GdkEventCrossing *event,
2617                                         gpointer         user_data)
2618 {
2619   GList *dev_list;
2620   GdkDevice *dev;
2621
2622 #ifdef INPUT_DEBUG
2623   printf("DEBUG: leave notify (mode=%d, details=%d)\n", event->mode, event->detail);
2624 #endif
2625     /* emergency disable XInput to avoid segfaults (GTK+ 2.17) or 
2626        interface non-responsiveness (GTK+ 2.18) */
2627   if (!gtk_check_version(2, 17, 0)) {
2628     gdk_flush();
2629     gdk_error_trap_push();
2630     for (dev_list = gdk_devices_list(); dev_list != NULL; dev_list = dev_list->next) {
2631       dev = GDK_DEVICE(dev_list->data);
2632       gdk_device_set_mode(dev, GDK_MODE_DISABLED);
2633     }
2634     ui.saved_is_corestroke = ui.is_corestroke;
2635     ui.is_corestroke = TRUE;
2636     gdk_flush();
2637     gdk_error_trap_pop();
2638   }
2639   return FALSE;
2640 }
2641
2642
2643 gboolean
2644 on_canvas_expose_event                 (GtkWidget       *widget,
2645                                         GdkEventExpose  *event,
2646                                         gpointer         user_data)
2647 {
2648   if (ui.view_continuous && ui.progressive_bg) rescale_bg_pixmaps();
2649   return FALSE;
2650 }
2651
2652
2653 gboolean
2654 on_canvas_key_press_event              (GtkWidget       *widget,
2655                                         GdkEventKey     *event,
2656                                         gpointer         user_data)
2657 {
2658   GtkAdjustment *adj;
2659   gint pgheight;
2660
2661   // Esc leaves text edition, or leaves fullscreen mode
2662   if (event->keyval == GDK_Escape) {
2663     if (ui.cur_item_type == ITEM_TEXT) { 
2664       end_text(); 
2665       return TRUE;
2666     }
2667     else if (ui.fullscreen) {
2668       do_fullscreen(FALSE);
2669       return TRUE;
2670     }
2671     else return FALSE;
2672   }
2673   
2674   /* In single page mode, switch pages with PgUp/PgDn (or Up/Dn) 
2675      when there's nowhere else to go. */
2676   pgheight = GTK_WIDGET(canvas)->allocation.height;
2677   adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(GET_COMPONENT("scrolledwindowMain")));
2678
2679   if (event->keyval == GDK_Page_Down || event->keyval == GDK_Down) {
2680     if (!ui.view_continuous && 
2681          (0.96 * ui.zoom * ui.cur_page->height < pgheight ||
2682           adj->value == adj->upper-pgheight)) 
2683     {
2684       end_text();
2685       if (ui.pageno < journal.npages-1)
2686         do_switch_page(ui.pageno+1, TRUE, FALSE);
2687       return TRUE;
2688     }
2689     if (adj->value == adj->upper-pgheight) return TRUE; // don't send focus away
2690   }
2691
2692   if (event->keyval == GDK_Page_Up || event->keyval == GDK_Up) {
2693     if (!ui.view_continuous && 
2694          (0.96 * ui.zoom * ui.cur_page->height < pgheight ||
2695           adj->value == adj->lower))
2696     {
2697       end_text();
2698       if (ui.pageno != 0) {
2699         do_switch_page(ui.pageno-1, TRUE, FALSE);
2700         gtk_adjustment_set_value(adj, adj->upper-pgheight);
2701       }
2702       return TRUE;
2703     }
2704     if (adj->value == adj->lower) return TRUE; // don't send focus away
2705   }
2706
2707   return FALSE;
2708 }
2709
2710
2711 gboolean
2712 on_canvas_motion_notify_event          (GtkWidget       *widget,
2713                                         GdkEventMotion  *event,
2714                                         gpointer         user_data)
2715 {
2716   gboolean looks_wrong, is_core;
2717   double pt[2];
2718   GdkModifierType mask;
2719
2720   /* we don't care about this event unless some operation is in progress;
2721      or if there's a selection (then we might want to change the mouse
2722      cursor to indicate the possibility of resizing) */  
2723   if (ui.cur_item_type == ITEM_NONE && ui.selection==NULL) return FALSE;
2724   if (ui.cur_item_type == ITEM_TEXT || ui.cur_item_type == ITEM_IMAGE) return FALSE;
2725
2726   is_core = (event->device == gdk_device_get_core_pointer());
2727   if (!ui.use_xinput && !is_core) return FALSE;
2728   if (!is_core) fix_xinput_coords((GdkEvent *)event);
2729   if (!finite_sized(event->x) || !finite_sized(event->y)) return FALSE; // Xorg 7.3 bug
2730
2731   if (ui.selection!=NULL && ui.cur_item_type == ITEM_NONE) {
2732     get_pointer_coords((GdkEvent *)event, pt);
2733     update_cursor_for_resize(pt);
2734     return FALSE;
2735   }
2736
2737   if (ui.use_xinput && is_core && !ui.is_corestroke) return FALSE;
2738   if (!is_core) ui.is_corestroke = FALSE;
2739
2740 #ifdef INPUT_DEBUG
2741   printf("DEBUG: MotionNotify (%s) (x,y)=(%.2f,%.2f), modifier %x\n", 
2742     is_core?"core":"xinput", event->x, event->y, event->state);
2743 #endif
2744   
2745   looks_wrong = !(event->state & (1<<(7+ui.which_mouse_button)));
2746   if (looks_wrong) {
2747     gdk_device_get_state(ui.stroke_device, event->window, NULL, &mask);
2748     looks_wrong = !(mask & (1<<(7+ui.which_mouse_button)));
2749   }
2750   
2751   if (looks_wrong) { /* mouse button shouldn't be up... give up */
2752     if (ui.cur_item_type == ITEM_STROKE) {
2753       finalize_stroke();
2754       if (ui.cur_brush->recognizer) recognize_patterns();
2755     }
2756     else if (ui.cur_item_type == ITEM_ERASURE) {
2757       finalize_erasure();
2758     }
2759     else if (ui.cur_item_type == ITEM_SELECTRECT) {
2760       finalize_selectrect();
2761     }
2762     else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2763       finalize_movesel();
2764     }
2765     else if (ui.cur_item_type == ITEM_RESIZESEL) {
2766       finalize_resizesel();
2767     }
2768     else if (ui.cur_item_type == ITEM_HAND) {
2769       ui.cur_item_type = ITEM_NONE;
2770     }
2771     switch_mapping(0);
2772     return FALSE;
2773   }
2774   
2775   if (ui.cur_item_type == ITEM_STROKE) {
2776     continue_stroke((GdkEvent *)event);
2777   }
2778   else if (ui.cur_item_type == ITEM_ERASURE) {
2779     do_eraser((GdkEvent *)event, ui.cur_brush->thickness/2,
2780                ui.cur_brush->tool_options == TOOLOPT_ERASER_STROKES);
2781   }
2782   else if (ui.cur_item_type == ITEM_SELECTRECT) {
2783     get_pointer_coords((GdkEvent *)event, pt);
2784     ui.selection->bbox.right = pt[0];
2785     ui.selection->bbox.bottom = pt[1];
2786     gnome_canvas_item_set(ui.selection->canvas_item,
2787                                "x2", pt[0], "y2", pt[1], NULL);
2788   }
2789   else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2790     continue_movesel((GdkEvent *)event);
2791   }
2792   else if (ui.cur_item_type == ITEM_RESIZESEL) {
2793     continue_resizesel((GdkEvent *)event);
2794   }
2795   else if (ui.cur_item_type == ITEM_HAND) {
2796     do_hand((GdkEvent *)event);
2797   }
2798   
2799   return FALSE;
2800 }
2801
2802 void
2803 on_comboLayer_changed                  (GtkComboBox     *combobox,
2804                                         gpointer         user_data)
2805 {
2806   int val;
2807
2808   if (ui.in_update_page_stuff) return; // avoid a bad retroaction
2809
2810   end_text();
2811
2812   val = gtk_combo_box_get_active(combobox);
2813   if (val == -1) return;
2814   val = ui.cur_page->nlayers-1-val;
2815   if (val == ui.layerno) return;
2816
2817   reset_selection();
2818   while (val>ui.layerno) {
2819     ui.layerno++;
2820     ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
2821     gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group));
2822   }
2823   while (val<ui.layerno) {
2824     gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group));
2825     ui.layerno--;
2826     if (ui.layerno<0) ui.cur_layer = NULL;
2827     else ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
2828   }
2829   update_page_stuff();
2830 }
2831
2832
2833 gboolean
2834 on_winMain_delete_event                (GtkWidget       *widget,
2835                                         GdkEvent        *event,
2836                                         gpointer         user_data)
2837 {
2838   end_text();
2839   if (ok_to_close()) gtk_main_quit();
2840   return TRUE;
2841 }
2842
2843
2844 void
2845 on_optionsUseXInput_activate           (GtkMenuItem     *menuitem,
2846                                         gpointer         user_data)
2847 {
2848   end_text();
2849   ui.allow_xinput = ui.use_xinput =
2850     gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2851
2852 /* HOW THINGS USED TO BE:
2853
2854    We'd like on_canvas_... to get BOTH core and xinput events. Up to
2855    GTK+ 2.16 this is achieved by making only the canvas's parent 
2856    GdkWindow xinput-aware, rather than the entire hierarchy.
2857    Otherwise, the proximity detection code in GDK is broken and 
2858    we'll lose core events.
2859    
2860    Up to GTK+ 2.10, gtk_widget_set_extension_events() only sets
2861    extension events for the widget's main window itself; in GTK+ 2.11
2862    also traverses GDK child windows that belong to the widget
2863    and sets their extension events too. We want to avoid that.
2864    So we use gdk_input_set_extension_events() directly on the canvas.
2865
2866    As much as possible, we'd like to keep doing this, though GTK+ 2.17
2867    is making our life harder (crasher bugs require us to disable XInput
2868    while editing text or using the layers combo box, but disabling
2869    XInput while in a XInput-aware window causes the interface to become
2870    non-responsive). 
2871 */
2872
2873 #ifndef WIN32
2874   if (!gtk_check_version(2, 17, 0)) {
2875 #endif
2876     /* GTK+ 2.17 and later: everybody shares a single native window,
2877        so we'll never get any core events, and we might as well set 
2878        extension events the way we're supposed to. Doing so helps solve 
2879        crasher bugs in 2.17, and prevents us from losing two-button
2880        events in 2.18 */
2881     gtk_widget_set_extension_events(GTK_WIDGET (canvas), 
2882        ui.use_xinput?GDK_EXTENSION_EVENTS_ALL:GDK_EXTENSION_EVENTS_NONE);
2883 #ifndef WIN32
2884   } else {
2885 #endif
2886     /* GTK+ 2.16 and earlier: we only activate extension events on the
2887        canvas's parent GdkWindow. This allows us to keep receiving core
2888        events. */
2889     gdk_input_set_extension_events(GTK_WIDGET(canvas)->window, 
2890       GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK,
2891       ui.use_xinput?GDK_EXTENSION_EVENTS_ALL:GDK_EXTENSION_EVENTS_NONE);
2892 #ifndef WIN32
2893   }
2894 #endif
2895   
2896   update_mappings_menu();
2897 }
2898
2899 void
2900 on_vscroll_changed                     (GtkAdjustment   *adjustment,
2901                                         gpointer         user_data)
2902 {
2903   gboolean need_update;
2904   double viewport_top, viewport_bottom;
2905   struct Page *tmppage;
2906   
2907   if (!ui.view_continuous) return;
2908   
2909   if (ui.progressive_bg) rescale_bg_pixmaps();
2910   need_update = FALSE;
2911   viewport_top = adjustment->value / ui.zoom;
2912   viewport_bottom = (adjustment->value + adjustment->page_size) / ui.zoom;
2913   tmppage = ui.cur_page;
2914   while (viewport_top > tmppage->voffset + tmppage->height) {
2915     if (ui.pageno == journal.npages-1) break;
2916     need_update = TRUE;
2917     ui.pageno++;
2918     tmppage = g_list_nth_data(journal.pages, ui.pageno);
2919   }
2920   while (viewport_bottom < tmppage->voffset) {
2921     if (ui.pageno == 0) break;
2922     need_update = TRUE;
2923     ui.pageno--;
2924     tmppage = g_list_nth_data(journal.pages, ui.pageno);
2925   }
2926   if (need_update) {
2927     end_text();
2928     do_switch_page(ui.pageno, FALSE, FALSE);
2929   }
2930   return;
2931 }
2932
2933 void
2934 on_spinPageNo_value_changed            (GtkSpinButton   *spinbutton,
2935                                         gpointer         user_data)
2936 {
2937   int val;
2938
2939   if (ui.in_update_page_stuff) return; // avoid a bad retroaction
2940
2941   /* in preparation for end_text(), send focus to the canvas if it's not ours.
2942      (avoid issues with Gtk trying to send focus to the dead text widget) */
2943
2944   if (!GTK_WIDGET_HAS_FOCUS(spinbutton))
2945     gtk_widget_grab_focus(GTK_WIDGET(canvas));
2946   end_text();
2947
2948   val = gtk_spin_button_get_value_as_int(spinbutton) - 1;
2949
2950   if (val == journal.npages) { // create a page at end
2951     on_journalNewPageEnd_activate(NULL, NULL);
2952     return;
2953   }
2954
2955   if (val == ui.pageno) return;
2956   if (val < 0) val = 0;
2957   if (val > journal.npages-1) val = journal.npages-1;
2958   do_switch_page(val, TRUE, FALSE);
2959 }
2960
2961
2962 void
2963 on_journalDefaultBackground_activate   (GtkMenuItem     *menuitem,
2964                                         gpointer         user_data)
2965 {
2966   struct Page *pg;
2967   GList *pglist;
2968   
2969   end_text();
2970   reset_selection();
2971   
2972   pg = ui.cur_page;
2973   for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
2974     if (ui.bg_apply_all_pages) pg = (struct Page *)pglist->data;
2975     prepare_new_undo();
2976     if (ui.bg_apply_all_pages) {
2977       if (pglist->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
2978       if (pglist->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
2979     }
2980     undo->type = ITEM_NEW_BG_RESIZE;
2981     undo->page = pg;
2982     undo->bg = pg->bg;
2983     undo->val_x = pg->width;
2984     undo->val_y = pg->height; 
2985     pg->bg = (struct Background *)g_memdup(ui.default_page.bg, sizeof(struct Background));
2986     pg->width = ui.default_page.width;
2987     pg->height = ui.default_page.height;
2988     pg->bg->canvas_item = undo->bg->canvas_item;
2989     undo->bg->canvas_item = NULL;
2990   
2991     make_page_clipbox(pg);
2992     update_canvas_bg(pg);
2993     if (!ui.bg_apply_all_pages) break;
2994   }
2995   do_switch_page(ui.pageno, TRUE, TRUE);
2996 }
2997
2998
2999 void
3000 on_journalSetAsDefault_activate        (GtkMenuItem     *menuitem,
3001                                         gpointer         user_data)
3002 {
3003   if (ui.cur_page->bg->type != BG_SOLID) return;
3004   
3005   end_text();
3006   prepare_new_undo();
3007   undo->type = ITEM_NEW_DEFAULT_BG;
3008   undo->val_x = ui.default_page.width;
3009   undo->val_y = ui.default_page.height;
3010   undo->bg = ui.default_page.bg;
3011   
3012   ui.default_page.width = ui.cur_page->width;
3013   ui.default_page.height = ui.cur_page->height;
3014   ui.default_page.bg = (struct Background *)g_memdup(ui.cur_page->bg, sizeof(struct Background));
3015   ui.default_page.bg->canvas_item = NULL;
3016 }
3017
3018
3019 void
3020 on_comboStdSizes_changed               (GtkComboBox     *combobox,
3021                                         gpointer         user_data)
3022 {
3023   GtkEntry *entry;
3024   GtkComboBox *comboUnit;
3025   int val;
3026   gchar text[20];
3027
3028   if (papersize_need_init) {
3029     gtk_combo_box_set_active(combobox, papersize_std);
3030     papersize_need_init = FALSE;
3031   } else {
3032     val = gtk_combo_box_get_active(combobox);
3033     if (val == -1 || val == papersize_std) return;
3034     papersize_std = val;
3035     if (val == STD_SIZE_CUSTOM) return;
3036     papersize_unit = std_units[val];
3037     papersize_width = std_widths[val];
3038     papersize_height = std_heights[val];
3039   }
3040   comboUnit = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboUnit"));
3041   gtk_combo_box_set_active(comboUnit, papersize_unit);
3042   entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryWidth"));
3043   g_snprintf(text, 20, "%.2f", papersize_width/unit_sizes[papersize_unit]);
3044   if (g_str_has_suffix(text, ".00")) 
3045     g_snprintf(text, 20, "%d", (int) (papersize_width/unit_sizes[papersize_unit]));
3046   gtk_entry_set_text(entry, text);
3047   entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryHeight"));
3048   g_snprintf(text, 20, "%.2f", papersize_height/unit_sizes[papersize_unit]);
3049   if (g_str_has_suffix(text, ".00")) 
3050     g_snprintf(text, 20, "%d", (int) (papersize_height/unit_sizes[papersize_unit]));
3051   gtk_entry_set_text(entry, text);
3052 }
3053
3054
3055 void
3056 on_entryWidth_changed                  (GtkEditable     *editable,
3057                                         gpointer         user_data)
3058 {
3059   double val;
3060   const gchar *text;
3061   gchar *ptr;
3062   GtkComboBox *comboStdSizes;
3063   
3064   text = gtk_entry_get_text(GTK_ENTRY(editable));
3065   val = strtod(text, &ptr);
3066   papersize_width_valid = (*ptr == 0 && val > 0.);
3067   if (!papersize_width_valid) return; // invalid entry
3068   val *= unit_sizes[papersize_unit];
3069   if (fabs(val - papersize_width) < 0.1) return; // no change
3070   papersize_std = STD_SIZE_CUSTOM;
3071   papersize_width = val;
3072   comboStdSizes = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboStdSizes"));
3073   gtk_combo_box_set_active(comboStdSizes, papersize_std);
3074 }
3075
3076
3077 void
3078 on_entryHeight_changed                 (GtkEditable     *editable,
3079                                         gpointer         user_data)
3080 {
3081   double val;
3082   const gchar *text;
3083   gchar *ptr;
3084   GtkComboBox *comboStdSizes;
3085   
3086   text = gtk_entry_get_text(GTK_ENTRY(editable));
3087   val = strtod(text, &ptr);
3088   papersize_height_valid = (*ptr == 0 && val > 0.);
3089   if (!papersize_height_valid) return; // invalid entry
3090   val *= unit_sizes[papersize_unit];
3091   if (fabs(val - papersize_height) < 0.1) return; // no change
3092   papersize_std = STD_SIZE_CUSTOM;
3093   papersize_height = val;
3094   comboStdSizes = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboStdSizes"));
3095   gtk_combo_box_set_active(comboStdSizes, papersize_std);
3096 }
3097
3098
3099 void
3100 on_comboUnit_changed                   (GtkComboBox     *combobox,
3101                                         gpointer         user_data)
3102 {
3103   GtkEntry *entry;
3104   int val;
3105   gchar text[20];
3106
3107   val = gtk_combo_box_get_active(combobox);
3108   if (val == -1 || val == papersize_unit) return;
3109   papersize_unit = val;
3110   entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryWidth"));
3111   if (papersize_width_valid) {
3112     g_snprintf(text, 20, "%.2f", papersize_width/unit_sizes[papersize_unit]);
3113     if (g_str_has_suffix(text, ".00")) 
3114       g_snprintf(text, 20, "%d", (int) (papersize_width/unit_sizes[papersize_unit]));
3115   } else *text = 0;
3116   gtk_entry_set_text(entry, text);
3117   if (papersize_height_valid) {
3118     entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryHeight"));
3119     g_snprintf(text, 20, "%.2f", papersize_height/unit_sizes[papersize_unit]);
3120     if (g_str_has_suffix(text, ".00")) 
3121       g_snprintf(text, 20, "%d", (int) (papersize_height/unit_sizes[papersize_unit]));
3122   } else *text = 0;
3123   gtk_entry_set_text(entry, text);
3124 }
3125
3126
3127 void
3128 on_viewFullscreen_activate             (GtkMenuItem     *menuitem,
3129                                         gpointer         user_data)
3130 {
3131   gboolean active;
3132   
3133   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
3134     active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3135   else
3136     active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
3137
3138   if (active == ui.fullscreen) return;
3139   do_fullscreen(active);
3140 }
3141
3142
3143 void
3144 on_optionsButtonMappings_activate      (GtkMenuItem     *menuitem,
3145                                         gpointer         user_data)
3146 {
3147   end_text();
3148   ui.use_erasertip =
3149     gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3150   update_mappings_menu();
3151 }
3152
3153
3154 void
3155 on_optionsProgressiveBG_activate       (GtkMenuItem     *menuitem,
3156                                         gpointer         user_data)
3157 {
3158   gboolean active;
3159   
3160   active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3161   if (ui.progressive_bg == active) return;
3162   end_text();
3163   ui.progressive_bg = active;
3164   if (!ui.progressive_bg) rescale_bg_pixmaps();
3165 }
3166
3167
3168 void
3169 on_mru_activate                        (GtkMenuItem     *menuitem,
3170                                         gpointer         user_data)
3171 {
3172   int which;
3173   gboolean success;
3174   GtkWidget *dialog;
3175   
3176   end_text();
3177   if (!ok_to_close()) return; // user aborted on save confirmation
3178   
3179   for (which = 0 ; which < MRU_SIZE; which++) {
3180     if (ui.mrumenu[which] == GTK_WIDGET(menuitem)) break;
3181   }
3182   if (which == MRU_SIZE || ui.mru[which] == NULL) return; // not found...
3183
3184   set_cursor_busy(TRUE);
3185   success = open_journal(ui.mru[which]);
3186   set_cursor_busy(FALSE);
3187   if (success) return;
3188
3189   /* open failed */
3190   dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
3191     GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening file '%s'"), ui.mru[which]);
3192   gtk_dialog_run(GTK_DIALOG(dialog));
3193   gtk_widget_destroy(dialog);
3194   delete_mru_entry(which);
3195 }
3196
3197
3198 void
3199 on_button2Pen_activate                 (GtkMenuItem     *menuitem,
3200                                         gpointer         user_data)
3201 {
3202   process_mapping_activate(menuitem, 1, TOOL_PEN);
3203 }
3204
3205
3206 void
3207 on_button2Eraser_activate              (GtkMenuItem     *menuitem,
3208                                         gpointer         user_data)
3209 {
3210   process_mapping_activate(menuitem, 1, TOOL_ERASER);
3211 }
3212
3213
3214 void
3215 on_button2Highlighter_activate         (GtkMenuItem     *menuitem,
3216                                         gpointer         user_data)
3217 {
3218   process_mapping_activate(menuitem, 1, TOOL_HIGHLIGHTER);
3219 }
3220
3221
3222 void
3223 on_button2Text_activate                (GtkMenuItem     *menuitem,
3224                                         gpointer         user_data)
3225 {
3226   process_mapping_activate(menuitem, 1, TOOL_TEXT);
3227 }
3228
3229
3230 void
3231 on_button2Image_activate               (GtkMenuItem     *menuitem,
3232                                         gpointer         user_data)
3233 {
3234   process_mapping_activate(menuitem, 1, TOOL_IMAGE);
3235 }
3236
3237
3238 void
3239 on_button2SelectRegion_activate        (GtkMenuItem     *menuitem,
3240                                         gpointer         user_data)
3241 {
3242   process_mapping_activate(menuitem, 1, TOOL_SELECTREGION);
3243 }
3244
3245
3246 void
3247 on_button2SelectRectangle_activate     (GtkMenuItem     *menuitem,
3248                                         gpointer         user_data)
3249 {
3250   process_mapping_activate(menuitem, 1, TOOL_SELECTRECT);
3251 }
3252
3253
3254 void
3255 on_button2VerticalSpace_activate       (GtkMenuItem     *menuitem,
3256                                         gpointer         user_data)
3257 {
3258   process_mapping_activate(menuitem, 1, TOOL_VERTSPACE);
3259 }
3260
3261
3262 void
3263 on_button2LinkBrush_activate           (GtkMenuItem     *menuitem,
3264                                         gpointer         user_data)
3265 {
3266   int i;
3267   
3268   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3269   end_text();
3270   ui.linked_brush[1] = BRUSH_LINKED;
3271   for (i=0;i<NUM_STROKE_TOOLS;i++) update_mapping_linkings(i);
3272 }
3273
3274
3275 void
3276 on_button2CopyBrush_activate           (GtkMenuItem     *menuitem,
3277                                         gpointer         user_data)
3278 {
3279   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3280   end_text();
3281   if (ui.toolno[1] >= NUM_STROKE_TOOLS) {
3282     ui.linked_brush[1] = BRUSH_STATIC;
3283     update_mappings_menu_linkings();
3284     return;
3285   }
3286   ui.linked_brush[1] = BRUSH_COPIED;
3287   g_memmove(&(ui.brushes[1][ui.toolno[1]]), &(ui.brushes[0][ui.toolno[1]]), sizeof(struct Brush));
3288 }
3289
3290
3291 void
3292 on_button3Pen_activate                 (GtkMenuItem     *menuitem,
3293                                         gpointer         user_data)
3294 {
3295   process_mapping_activate(menuitem, 2, TOOL_PEN);
3296 }
3297
3298
3299 void
3300 on_button3Eraser_activate              (GtkMenuItem     *menuitem,
3301                                         gpointer         user_data)
3302 {
3303   process_mapping_activate(menuitem, 2, TOOL_ERASER);
3304 }
3305
3306
3307 void
3308 on_button3Highlighter_activate         (GtkMenuItem     *menuitem,
3309                                         gpointer         user_data)
3310 {
3311   process_mapping_activate(menuitem, 2, TOOL_HIGHLIGHTER);
3312 }
3313
3314
3315 void
3316 on_button3Text_activate                (GtkMenuItem     *menuitem,
3317                                         gpointer         user_data)
3318 {
3319   process_mapping_activate(menuitem, 2, TOOL_TEXT);
3320 }
3321
3322
3323 void
3324 on_button3Image_activate               (GtkMenuItem     *menuitem,
3325                                         gpointer         user_data)
3326 {
3327   process_mapping_activate(menuitem, 2, TOOL_IMAGE);
3328 }
3329
3330
3331 void
3332 on_button3SelectRegion_activate        (GtkMenuItem     *menuitem,
3333                                         gpointer         user_data)
3334 {
3335   process_mapping_activate(menuitem, 2, TOOL_SELECTREGION);
3336 }
3337
3338
3339 void
3340 on_button3SelectRectangle_activate     (GtkMenuItem     *menuitem,
3341                                         gpointer         user_data)
3342 {
3343   process_mapping_activate(menuitem, 2, TOOL_SELECTRECT);
3344 }
3345
3346
3347 void
3348 on_button3VerticalSpace_activate       (GtkMenuItem     *menuitem,
3349                                         gpointer         user_data)
3350 {
3351   process_mapping_activate(menuitem, 2, TOOL_VERTSPACE);
3352 }
3353
3354
3355 void
3356 on_button3LinkBrush_activate           (GtkMenuItem     *menuitem,
3357                                         gpointer         user_data)
3358 {
3359   int i;
3360   
3361   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3362   end_text();
3363   ui.linked_brush[2] = BRUSH_LINKED;
3364   for (i=0;i<NUM_STROKE_TOOLS;i++) update_mapping_linkings(i);
3365 }
3366
3367
3368 void
3369 on_button3CopyBrush_activate           (GtkMenuItem     *menuitem,
3370                                         gpointer         user_data)
3371 {
3372   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3373   end_text();
3374   if (ui.toolno[2] >= NUM_STROKE_TOOLS) {
3375     ui.linked_brush[2] = BRUSH_STATIC;
3376     update_mappings_menu_linkings();
3377     return;
3378   }
3379   ui.linked_brush[2] = BRUSH_COPIED;
3380   g_memmove(&(ui.brushes[2][ui.toolno[2]]), &(ui.brushes[0][ui.toolno[2]]), sizeof(struct Brush));
3381 }
3382
3383 // the set zoom dialog
3384
3385 GtkWidget *zoom_dialog;
3386 double zoom_percent;
3387
3388 void
3389 on_viewSetZoom_activate                (GtkMenuItem     *menuitem,
3390                                         gpointer         user_data)
3391 {
3392   int response;
3393   double test_w, test_h;
3394   GtkSpinButton *spinZoom;
3395   
3396   end_text();
3397   zoom_dialog = create_zoomDialog();
3398   zoom_percent = 100*ui.zoom / DEFAULT_ZOOM;
3399   spinZoom = GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(zoom_dialog), "spinZoom"));
3400   gtk_spin_button_set_increments(spinZoom, ui.zoom_step_increment, 5*ui.zoom_step_increment);
3401   gtk_spin_button_set_value(spinZoom, zoom_percent);
3402   test_w = 100*(GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width/DEFAULT_ZOOM;
3403   test_h = 100*(GTK_WIDGET(canvas))->allocation.height/ui.cur_page->height/DEFAULT_ZOOM;
3404   if (zoom_percent > 99.9 && zoom_percent < 100.1) 
3405     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3406            G_OBJECT(zoom_dialog), "radioZoom100")), TRUE);
3407   else if (zoom_percent > test_w-0.1 && zoom_percent < test_w+0.1)
3408     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3409            G_OBJECT(zoom_dialog), "radioZoomWidth")), TRUE);
3410   else if (zoom_percent > test_h-0.1 && zoom_percent < test_h+0.1)
3411     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3412            G_OBJECT(zoom_dialog), "radioZoomHeight")), TRUE);
3413   else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3414            G_OBJECT(zoom_dialog), "radioZoom")), TRUE);
3415   gtk_widget_show(zoom_dialog);
3416   
3417   do {
3418     response = gtk_dialog_run(GTK_DIALOG(zoom_dialog));
3419     if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY) {
3420       ui.zoom = DEFAULT_ZOOM*zoom_percent/100;
3421       gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
3422       rescale_text_items();
3423       rescale_bg_pixmaps();
3424       rescale_images();
3425     }
3426   } while (response == GTK_RESPONSE_APPLY);
3427   
3428   gtk_widget_destroy(zoom_dialog);
3429 }
3430
3431
3432 void
3433 on_spinZoom_value_changed              (GtkSpinButton   *spinbutton,
3434                                         gpointer         user_data)
3435 {
3436   double val;
3437
3438   val = gtk_spin_button_get_value(GTK_SPIN_BUTTON(g_object_get_data(
3439              G_OBJECT(zoom_dialog), "spinZoom")));
3440   if (val<1) return;
3441   if (val<10) val=10.;
3442   if (val>1500) val=1500.;
3443   if (val<zoom_percent-1 || val>zoom_percent+1)
3444     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3445            G_OBJECT(zoom_dialog), "radioZoom")), TRUE);
3446   zoom_percent = val;
3447 }
3448
3449
3450 void
3451 on_radioZoom_toggled                   (GtkToggleButton *togglebutton,
3452                                         gpointer         user_data)
3453 {
3454   // nothing to do
3455 }
3456
3457
3458 void
3459 on_radioZoom100_toggled                (GtkToggleButton *togglebutton,
3460                                         gpointer         user_data)
3461 {
3462   if (!gtk_toggle_button_get_active(togglebutton)) return;
3463   zoom_percent = 100.;
3464   gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3465         G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3466 }
3467
3468
3469 void
3470 on_radioZoomWidth_toggled              (GtkToggleButton *togglebutton,
3471                                         gpointer         user_data)
3472 {
3473   if (!gtk_toggle_button_get_active(togglebutton)) return;
3474   zoom_percent = 100*(GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width/DEFAULT_ZOOM;
3475   gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3476         G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3477 }
3478
3479
3480 void
3481 on_radioZoomHeight_toggled             (GtkToggleButton *togglebutton,
3482                                         gpointer         user_data)
3483 {
3484   if (!gtk_toggle_button_get_active(togglebutton)) return;
3485   zoom_percent = 100*(GTK_WIDGET(canvas))->allocation.height/ui.cur_page->height/DEFAULT_ZOOM;
3486   gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3487         G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3488 }
3489
3490
3491 void
3492 on_toolsHand_activate                  (GtkMenuItem     *menuitem,
3493                                         gpointer         user_data)
3494 {
3495   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
3496     if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
3497       return;
3498   } else {
3499     if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
3500       return;
3501   }
3502
3503   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
3504   if (ui.toolno[ui.cur_mapping] == TOOL_HAND) return;
3505
3506   ui.cur_mapping = 0;
3507   end_text();
3508   reset_selection();
3509   ui.toolno[ui.cur_mapping] = TOOL_HAND;
3510   update_mapping_linkings(-1);
3511   update_tool_buttons();
3512   update_tool_menu();
3513   update_color_menu();
3514   update_cursor();
3515 }
3516
3517
3518 void
3519 on_button2Hand_activate                (GtkMenuItem     *menuitem,
3520                                         gpointer         user_data)
3521 {
3522   process_mapping_activate(menuitem, 1, TOOL_HAND);
3523 }
3524
3525
3526 void
3527 on_button3Hand_activate                (GtkMenuItem     *menuitem,
3528                                         gpointer         user_data)
3529 {
3530   process_mapping_activate(menuitem, 2, TOOL_HAND);
3531 }
3532
3533
3534 void
3535 on_optionsPrintRuling_activate         (GtkMenuItem     *menuitem,
3536                                         gpointer         user_data)
3537 {
3538   end_text();
3539   ui.print_ruling = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3540 }
3541
3542 void
3543 on_optionsAutoloadPdfXoj_activate      (GtkMenuItem     *menuitem,
3544                                         gpointer         user_data)
3545 {
3546   end_text();
3547   ui.autoload_pdf_xoj = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3548 }
3549
3550 void
3551 on_fontButton_font_set                 (GtkFontButton   *fontbutton,
3552                                         gpointer         user_data)
3553 {
3554   gchar *str;
3555   
3556   str = g_strdup(gtk_font_button_get_font_name(fontbutton));
3557   process_font_sel(str);
3558 }
3559
3560 void
3561 on_optionsLeftHanded_activate          (GtkMenuItem     *menuitem,   
3562                                         gpointer         user_data)
3563 {
3564   end_text();
3565   ui.left_handed = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3566   gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW(GET_COMPONENT("scrolledwindowMain")),
3567     ui.left_handed?GTK_CORNER_TOP_RIGHT:GTK_CORNER_TOP_LEFT);
3568 }
3569
3570 void
3571 on_optionsShortenMenus_activate        (GtkMenuItem     *menuitem,  
3572                                         gpointer         user_data)
3573 {
3574   gchar *item, *nextptr;
3575   GtkWidget *w;
3576   
3577   end_text();
3578   ui.shorten_menus = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3579   
3580   /* go over the item list */
3581   item = ui.shorten_menu_items;
3582   while (*item==' ') item++;
3583   while (*item) {
3584     nextptr = strchr(item, ' ');
3585     if (nextptr!=NULL) *nextptr = 0;
3586     // hide or show the item
3587     w = GET_COMPONENT(item);
3588     if (w != NULL) {
3589       if (ui.shorten_menus) gtk_widget_hide(w);
3590       else gtk_widget_show(w);
3591     }
3592     // next item
3593     if (nextptr==NULL) break;
3594     *nextptr = ' ';
3595     item = nextptr;
3596     while (*item==' ') item++;
3597   }
3598   
3599   // just in case someone tried to unhide stuff they shouldn't be seeing
3600   hide_unimplemented();
3601   // maybe we should also make sure the drawing area stays visible ?
3602 }
3603
3604 void
3605 on_optionsAutoSavePrefs_activate       (GtkMenuItem     *menuitem,  
3606                                         gpointer         user_data)
3607 {
3608   end_text();
3609   ui.auto_save_prefs = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3610 }
3611
3612 void
3613 on_optionsPressureSensitive_activate   (GtkMenuItem     *menuitem,
3614                                         gpointer         user_data)
3615 {
3616   int i;
3617   end_text();
3618   ui.pressure_sensitivity =
3619     gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3620   for (i=0; i<=NUM_BUTTONS; i++)
3621     ui.brushes[i][TOOL_PEN].variable_width = ui.pressure_sensitivity;
3622   update_mappings_menu();
3623 }
3624
3625
3626 void
3627 on_buttonColorChooser_set              (GtkColorButton  *colorbutton,
3628                                         gpointer         user_data)
3629 {
3630   GdkColor gdkcolor;
3631   guint16 alpha;
3632   
3633   gtk_color_button_get_color(colorbutton, &gdkcolor);
3634   alpha = gtk_color_button_get_alpha(colorbutton);
3635   process_color_activate((GtkMenuItem*)colorbutton, COLOR_OTHER, gdkcolor_to_rgba(gdkcolor, alpha));
3636 }
3637
3638
3639 void
3640 on_optionsButtonsSwitchMappings_activate(GtkMenuItem    *menuitem,
3641                                         gpointer         user_data)
3642 {
3643   end_text();
3644   switch_mapping(0);
3645   ui.button_switch_mapping = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3646 }
3647
3648