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