]> git.donarmstrong.com Git - xournal.git/blob - src/xo-callbacks.c
Lasso selection tool; prepare for release 0.4.7
[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     get_pointer_coords((GdkEvent *)event, ui.cur_path.coords);
2461   }
2462   if (ui.cur_item_type != ITEM_NONE) return FALSE; // we're already doing something
2463
2464   // if button_switch_mapping enabled, button 2 or 3 clicks only switch mapping
2465   if (ui.button_switch_mapping && event->button > 1) {
2466     ui.which_unswitch_button = event->button;
2467     switch_mapping(event->button-1);
2468     return FALSE;
2469   }
2470
2471   ui.is_corestroke = is_core;
2472   ui.stroke_device = event->device;
2473
2474   if (ui.use_erasertip && event->device->source == GDK_SOURCE_ERASER)
2475     mapping = NUM_BUTTONS;
2476   else if (ui.button_switch_mapping) {
2477     mapping = ui.cur_mapping;
2478     if (!mapping && (event->state & GDK_BUTTON2_MASK)) mapping = 1;
2479     if (!mapping && (event->state & GDK_BUTTON3_MASK)) mapping = 2;
2480   }
2481   else mapping = event->button-1;
2482
2483   // check whether we're in a page
2484   get_pointer_coords((GdkEvent *)event, pt);
2485   set_current_page(pt);
2486   
2487   // can't paint on the background...
2488
2489   if (ui.cur_layer == NULL) {
2490     /* warn */
2491     dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL,
2492       GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("Drawing is not allowed on the "
2493       "background layer.\n Switching to Layer 1."));
2494     gtk_dialog_run(GTK_DIALOG(dialog));
2495     gtk_widget_destroy(dialog);
2496     on_viewShowLayer_activate(NULL, NULL);
2497     return FALSE;
2498   }
2499
2500   // switch mappings if needed
2501   
2502   ui.which_mouse_button = event->button;
2503   switch_mapping(mapping);
2504 #ifdef WIN32
2505   update_cursor();
2506 #endif
2507
2508   // in text tool, clicking in a text area edits it
2509   if (ui.toolno[mapping] == TOOL_TEXT) {
2510     item = click_is_in_text(ui.cur_layer, pt[0], pt[1]);
2511     if (item!=NULL) { 
2512       reset_selection();
2513       start_text((GdkEvent *)event, item);
2514       return FALSE;
2515     }
2516   }
2517
2518   // if this can be a selection move or resize, then it takes precedence over anything else  
2519   if (start_resizesel((GdkEvent *)event)) return FALSE;
2520   if (start_movesel((GdkEvent *)event)) return FALSE;
2521   
2522   if (ui.toolno[mapping] != TOOL_SELECTREGION && ui.toolno[mapping] != TOOL_SELECTRECT)
2523     reset_selection();
2524
2525   // process the event
2526   
2527   if (ui.toolno[mapping] == TOOL_HAND) {
2528     ui.cur_item_type = ITEM_HAND;
2529     get_pointer_coords((GdkEvent *)event, ui.hand_refpt);
2530     ui.hand_refpt[0] += ui.cur_page->hoffset;
2531     ui.hand_refpt[1] += ui.cur_page->voffset;
2532   } 
2533   else if (ui.toolno[mapping] == TOOL_PEN || ui.toolno[mapping] == TOOL_HIGHLIGHTER ||
2534         (ui.toolno[mapping] == TOOL_ERASER && ui.cur_brush->tool_options == TOOLOPT_ERASER_WHITEOUT)) {
2535     create_new_stroke((GdkEvent *)event);
2536   } 
2537   else if (ui.toolno[mapping] == TOOL_ERASER) {
2538     ui.cur_item_type = ITEM_ERASURE;
2539     do_eraser((GdkEvent *)event, ui.cur_brush->thickness/2,
2540                ui.cur_brush->tool_options == TOOLOPT_ERASER_STROKES);
2541   }
2542   else if (ui.toolno[mapping] == TOOL_SELECTREGION) {
2543     start_selectregion((GdkEvent *)event);
2544   }
2545   else if (ui.toolno[mapping] == TOOL_SELECTRECT) {
2546     start_selectrect((GdkEvent *)event);
2547   }
2548   else if (ui.toolno[mapping] == TOOL_VERTSPACE) {
2549     start_vertspace((GdkEvent *)event);
2550   }
2551   else if (ui.toolno[mapping] == TOOL_TEXT) {
2552     start_text((GdkEvent *)event, NULL);
2553   }
2554   else if (ui.toolno[mapping] == TOOL_IMAGE) {
2555     insert_image((GdkEvent *)event);
2556   }
2557   return FALSE;
2558 }
2559
2560
2561 gboolean
2562 on_canvas_button_release_event         (GtkWidget       *widget,
2563                                         GdkEventButton  *event,
2564                                         gpointer         user_data)
2565 {
2566   gboolean is_core;
2567   
2568 #ifdef INPUT_DEBUG
2569   printf("DEBUG: ButtonRelease (%s) (x,y)=(%.2f,%.2f), button %d, modifier %x\n", 
2570       event->device->name, event->x, event->y, event->button, event->state);
2571 #endif
2572
2573   is_core = (event->device == gdk_device_get_core_pointer());
2574   if (!ui.use_xinput && !is_core) return FALSE;
2575   if (ui.use_xinput && is_core && !ui.is_corestroke) return FALSE;
2576   if (!is_core) fix_xinput_coords((GdkEvent *)event);
2577
2578   if (event->button != ui.which_mouse_button && 
2579       event->button != ui.which_unswitch_button)
2580     return FALSE;
2581
2582   if (ui.cur_item_type == ITEM_STROKE) {
2583     finalize_stroke();
2584     if (ui.cur_brush->recognizer) recognize_patterns();
2585   }
2586   else if (ui.cur_item_type == ITEM_ERASURE) {
2587     finalize_erasure();
2588   }
2589   else if (ui.cur_item_type == ITEM_SELECTREGION) {
2590     finalize_selectregion();
2591   }
2592   else if (ui.cur_item_type == ITEM_SELECTRECT) {
2593     finalize_selectrect();
2594   }
2595   else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2596     finalize_movesel();
2597   }
2598   else if (ui.cur_item_type == ITEM_RESIZESEL) {
2599     finalize_resizesel();
2600   }
2601   else if (ui.cur_item_type == ITEM_HAND) {
2602     ui.cur_item_type = ITEM_NONE;
2603   }
2604   
2605   if (!ui.which_unswitch_button || event->button == ui.which_unswitch_button)
2606     switch_mapping(0); // will reset ui.which_unswitch_button
2607
2608   return FALSE;
2609 }
2610
2611
2612 gboolean
2613 on_canvas_enter_notify_event           (GtkWidget       *widget,
2614                                         GdkEventCrossing *event,
2615                                         gpointer         user_data)
2616 {
2617   GList *dev_list;
2618   GdkDevice *dev;
2619
2620 #ifdef INPUT_DEBUG
2621   printf("DEBUG: enter notify\n");
2622 #endif
2623     /* re-enable input devices after they've been emergency-disabled
2624        by leave_notify */
2625   if (!gtk_check_version(2, 17, 0)) {
2626     gdk_flush();
2627     gdk_error_trap_push();
2628     for (dev_list = gdk_devices_list(); dev_list != NULL; dev_list = dev_list->next) {
2629       dev = GDK_DEVICE(dev_list->data);
2630       gdk_device_set_mode(dev, GDK_MODE_SCREEN);
2631     }
2632     ui.is_corestroke = ui.saved_is_corestroke;
2633     gdk_flush();
2634     gdk_error_trap_pop();
2635   }
2636   return FALSE;
2637 }
2638
2639 gboolean
2640 on_canvas_leave_notify_event           (GtkWidget       *widget,
2641                                         GdkEventCrossing *event,
2642                                         gpointer         user_data)
2643 {
2644   GList *dev_list;
2645   GdkDevice *dev;
2646
2647 #ifdef INPUT_DEBUG
2648   printf("DEBUG: leave notify (mode=%d, details=%d)\n", event->mode, event->detail);
2649 #endif
2650     /* emergency disable XInput to avoid segfaults (GTK+ 2.17) or 
2651        interface non-responsiveness (GTK+ 2.18) */
2652   if (!gtk_check_version(2, 17, 0)) {
2653     gdk_flush();
2654     gdk_error_trap_push();
2655     for (dev_list = gdk_devices_list(); dev_list != NULL; dev_list = dev_list->next) {
2656       dev = GDK_DEVICE(dev_list->data);
2657       gdk_device_set_mode(dev, GDK_MODE_DISABLED);
2658     }
2659     ui.saved_is_corestroke = ui.is_corestroke;
2660     ui.is_corestroke = TRUE;
2661     gdk_flush();
2662     gdk_error_trap_pop();
2663   }
2664   return FALSE;
2665 }
2666
2667
2668 gboolean
2669 on_canvas_expose_event                 (GtkWidget       *widget,
2670                                         GdkEventExpose  *event,
2671                                         gpointer         user_data)
2672 {
2673   if (ui.view_continuous && ui.progressive_bg) rescale_bg_pixmaps();
2674   return FALSE;
2675 }
2676
2677
2678 gboolean
2679 on_canvas_key_press_event              (GtkWidget       *widget,
2680                                         GdkEventKey     *event,
2681                                         gpointer         user_data)
2682 {
2683   GtkAdjustment *adj;
2684   gint pgheight;
2685
2686   // Esc leaves text edition, or leaves fullscreen mode
2687   if (event->keyval == GDK_Escape) {
2688     if (ui.cur_item_type == ITEM_TEXT) { 
2689       end_text(); 
2690       return TRUE;
2691     }
2692     else if (ui.fullscreen) {
2693       do_fullscreen(FALSE);
2694       return TRUE;
2695     }
2696     else return FALSE;
2697   }
2698   
2699   /* In single page mode, switch pages with PgUp/PgDn (or Up/Dn) 
2700      when there's nowhere else to go. */
2701   pgheight = GTK_WIDGET(canvas)->allocation.height;
2702   adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(GET_COMPONENT("scrolledwindowMain")));
2703
2704   if (event->keyval == GDK_Page_Down || event->keyval == GDK_Down) {
2705     if (!ui.view_continuous && 
2706          (0.96 * ui.zoom * ui.cur_page->height < pgheight ||
2707           adj->value == adj->upper-pgheight)) 
2708     {
2709       end_text();
2710       if (ui.pageno < journal.npages-1)
2711         do_switch_page(ui.pageno+1, TRUE, FALSE);
2712       return TRUE;
2713     }
2714     if (adj->value == adj->upper-pgheight) return TRUE; // don't send focus away
2715   }
2716
2717   if (event->keyval == GDK_Page_Up || event->keyval == GDK_Up) {
2718     if (!ui.view_continuous && 
2719          (0.96 * ui.zoom * ui.cur_page->height < pgheight ||
2720           adj->value == adj->lower))
2721     {
2722       end_text();
2723       if (ui.pageno != 0) {
2724         do_switch_page(ui.pageno-1, TRUE, FALSE);
2725         gtk_adjustment_set_value(adj, adj->upper-pgheight);
2726       }
2727       return TRUE;
2728     }
2729     if (adj->value == adj->lower) return TRUE; // don't send focus away
2730   }
2731
2732   return FALSE;
2733 }
2734
2735
2736 gboolean
2737 on_canvas_motion_notify_event          (GtkWidget       *widget,
2738                                         GdkEventMotion  *event,
2739                                         gpointer         user_data)
2740 {
2741   gboolean looks_wrong, is_core;
2742   double pt[2];
2743   GdkModifierType mask;
2744
2745   /* we don't care about this event unless some operation is in progress;
2746      or if there's a selection (then we might want to change the mouse
2747      cursor to indicate the possibility of resizing) */  
2748   if (ui.cur_item_type == ITEM_NONE && ui.selection==NULL) return FALSE;
2749   if (ui.cur_item_type == ITEM_TEXT || ui.cur_item_type == ITEM_IMAGE) return FALSE;
2750
2751   is_core = (event->device == gdk_device_get_core_pointer());
2752   if (!ui.use_xinput && !is_core) return FALSE;
2753   if (!is_core) fix_xinput_coords((GdkEvent *)event);
2754   if (!finite_sized(event->x) || !finite_sized(event->y)) return FALSE; // Xorg 7.3 bug
2755
2756   if (ui.selection!=NULL && ui.cur_item_type == ITEM_NONE) {
2757     get_pointer_coords((GdkEvent *)event, pt);
2758     update_cursor_for_resize(pt);
2759     return FALSE;
2760   }
2761
2762   if (ui.use_xinput && is_core && !ui.is_corestroke) return FALSE;
2763   if (!is_core) ui.is_corestroke = FALSE;
2764
2765 #ifdef INPUT_DEBUG
2766   printf("DEBUG: MotionNotify (%s) (x,y)=(%.2f,%.2f), modifier %x\n", 
2767     is_core?"core":"xinput", event->x, event->y, event->state);
2768 #endif
2769   
2770   looks_wrong = !(event->state & (1<<(7+ui.which_mouse_button)));
2771   if (looks_wrong) {
2772     gdk_device_get_state(ui.stroke_device, event->window, NULL, &mask);
2773     looks_wrong = !(mask & (1<<(7+ui.which_mouse_button)));
2774   }
2775   
2776   if (looks_wrong) { /* mouse button shouldn't be up... give up */
2777     if (ui.cur_item_type == ITEM_STROKE) {
2778       finalize_stroke();
2779       if (ui.cur_brush->recognizer) recognize_patterns();
2780     }
2781     else if (ui.cur_item_type == ITEM_ERASURE) {
2782       finalize_erasure();
2783     }
2784     else if (ui.cur_item_type == ITEM_SELECTREGION) {
2785       finalize_selectregion();
2786     }
2787     else if (ui.cur_item_type == ITEM_SELECTRECT) {
2788       finalize_selectrect();
2789     }
2790     else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2791       finalize_movesel();
2792     }
2793     else if (ui.cur_item_type == ITEM_RESIZESEL) {
2794       finalize_resizesel();
2795     }
2796     else if (ui.cur_item_type == ITEM_HAND) {
2797       ui.cur_item_type = ITEM_NONE;
2798     }
2799     switch_mapping(0);
2800     return FALSE;
2801   }
2802   
2803   if (ui.cur_item_type == ITEM_STROKE) {
2804     continue_stroke((GdkEvent *)event);
2805   }
2806   else if (ui.cur_item_type == ITEM_ERASURE) {
2807     do_eraser((GdkEvent *)event, ui.cur_brush->thickness/2,
2808                ui.cur_brush->tool_options == TOOLOPT_ERASER_STROKES);
2809   }
2810   else if (ui.cur_item_type == ITEM_SELECTREGION) {
2811     continue_selectregion((GdkEvent *)event);
2812   }
2813   else if (ui.cur_item_type == ITEM_SELECTRECT) {
2814     get_pointer_coords((GdkEvent *)event, pt);
2815     ui.selection->bbox.right = pt[0];
2816     ui.selection->bbox.bottom = pt[1];
2817     gnome_canvas_item_set(ui.selection->canvas_item,
2818                                "x2", pt[0], "y2", pt[1], NULL);
2819   }
2820   else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2821     continue_movesel((GdkEvent *)event);
2822   }
2823   else if (ui.cur_item_type == ITEM_RESIZESEL) {
2824     continue_resizesel((GdkEvent *)event);
2825   }
2826   else if (ui.cur_item_type == ITEM_HAND) {
2827     do_hand((GdkEvent *)event);
2828   }
2829   
2830   return FALSE;
2831 }
2832
2833 void
2834 on_comboLayer_changed                  (GtkComboBox     *combobox,
2835                                         gpointer         user_data)
2836 {
2837   int val;
2838
2839   if (ui.in_update_page_stuff) return; // avoid a bad retroaction
2840
2841   end_text();
2842
2843   val = gtk_combo_box_get_active(combobox);
2844   if (val == -1) return;
2845   val = ui.cur_page->nlayers-1-val;
2846   if (val == ui.layerno) return;
2847
2848   reset_selection();
2849   while (val>ui.layerno) {
2850     ui.layerno++;
2851     ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
2852     gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group));
2853   }
2854   while (val<ui.layerno) {
2855     gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group));
2856     ui.layerno--;
2857     if (ui.layerno<0) ui.cur_layer = NULL;
2858     else ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
2859   }
2860   update_page_stuff();
2861 }
2862
2863
2864 gboolean
2865 on_winMain_delete_event                (GtkWidget       *widget,
2866                                         GdkEvent        *event,
2867                                         gpointer         user_data)
2868 {
2869   end_text();
2870   if (ok_to_close()) gtk_main_quit();
2871   return TRUE;
2872 }
2873
2874
2875 void
2876 on_optionsUseXInput_activate           (GtkMenuItem     *menuitem,
2877                                         gpointer         user_data)
2878 {
2879   end_text();
2880   ui.allow_xinput = ui.use_xinput =
2881     gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2882
2883 /* HOW THINGS USED TO BE:
2884
2885    We'd like on_canvas_... to get BOTH core and xinput events. Up to
2886    GTK+ 2.16 this is achieved by making only the canvas's parent 
2887    GdkWindow xinput-aware, rather than the entire hierarchy.
2888    Otherwise, the proximity detection code in GDK is broken and 
2889    we'll lose core events.
2890    
2891    Up to GTK+ 2.10, gtk_widget_set_extension_events() only sets
2892    extension events for the widget's main window itself; in GTK+ 2.11
2893    also traverses GDK child windows that belong to the widget
2894    and sets their extension events too. We want to avoid that.
2895    So we use gdk_input_set_extension_events() directly on the canvas.
2896
2897    As much as possible, we'd like to keep doing this, though GTK+ 2.17
2898    is making our life harder (crasher bugs require us to disable XInput
2899    while editing text or using the layers combo box, but disabling
2900    XInput while in a XInput-aware window causes the interface to become
2901    non-responsive). 
2902 */
2903
2904 #ifndef WIN32
2905   if (!gtk_check_version(2, 17, 0)) {
2906 #endif
2907     /* GTK+ 2.17 and later: everybody shares a single native window,
2908        so we'll never get any core events, and we might as well set 
2909        extension events the way we're supposed to. Doing so helps solve 
2910        crasher bugs in 2.17, and prevents us from losing two-button
2911        events in 2.18 */
2912     gtk_widget_set_extension_events(GTK_WIDGET (canvas), 
2913        ui.use_xinput?GDK_EXTENSION_EVENTS_ALL:GDK_EXTENSION_EVENTS_NONE);
2914 #ifndef WIN32
2915   } else {
2916 #endif
2917     /* GTK+ 2.16 and earlier: we only activate extension events on the
2918        canvas's parent GdkWindow. This allows us to keep receiving core
2919        events. */
2920     gdk_input_set_extension_events(GTK_WIDGET(canvas)->window, 
2921       GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK,
2922       ui.use_xinput?GDK_EXTENSION_EVENTS_ALL:GDK_EXTENSION_EVENTS_NONE);
2923 #ifndef WIN32
2924   }
2925 #endif
2926   
2927   update_mappings_menu();
2928 }
2929
2930 void
2931 on_vscroll_changed                     (GtkAdjustment   *adjustment,
2932                                         gpointer         user_data)
2933 {
2934   gboolean need_update;
2935   double viewport_top, viewport_bottom;
2936   struct Page *tmppage;
2937   
2938   if (!ui.view_continuous) return;
2939   
2940   if (ui.progressive_bg) rescale_bg_pixmaps();
2941   need_update = FALSE;
2942   viewport_top = adjustment->value / ui.zoom;
2943   viewport_bottom = (adjustment->value + adjustment->page_size) / ui.zoom;
2944   tmppage = ui.cur_page;
2945   while (viewport_top > tmppage->voffset + tmppage->height) {
2946     if (ui.pageno == journal.npages-1) break;
2947     need_update = TRUE;
2948     ui.pageno++;
2949     tmppage = g_list_nth_data(journal.pages, ui.pageno);
2950   }
2951   while (viewport_bottom < tmppage->voffset) {
2952     if (ui.pageno == 0) break;
2953     need_update = TRUE;
2954     ui.pageno--;
2955     tmppage = g_list_nth_data(journal.pages, ui.pageno);
2956   }
2957   if (need_update) {
2958     end_text();
2959     do_switch_page(ui.pageno, FALSE, FALSE);
2960   }
2961   return;
2962 }
2963
2964 void
2965 on_spinPageNo_value_changed            (GtkSpinButton   *spinbutton,
2966                                         gpointer         user_data)
2967 {
2968   int val;
2969
2970   if (ui.in_update_page_stuff) return; // avoid a bad retroaction
2971
2972   /* in preparation for end_text(), send focus to the canvas if it's not ours.
2973      (avoid issues with Gtk trying to send focus to the dead text widget) */
2974
2975   if (!GTK_WIDGET_HAS_FOCUS(spinbutton))
2976     gtk_widget_grab_focus(GTK_WIDGET(canvas));
2977   end_text();
2978
2979   val = gtk_spin_button_get_value_as_int(spinbutton) - 1;
2980
2981   if (val == journal.npages) { // create a page at end
2982     on_journalNewPageEnd_activate(NULL, NULL);
2983     return;
2984   }
2985
2986   if (val == ui.pageno) return;
2987   if (val < 0) val = 0;
2988   if (val > journal.npages-1) val = journal.npages-1;
2989   do_switch_page(val, TRUE, FALSE);
2990 }
2991
2992
2993 void
2994 on_journalDefaultBackground_activate   (GtkMenuItem     *menuitem,
2995                                         gpointer         user_data)
2996 {
2997   struct Page *pg;
2998   GList *pglist;
2999   
3000   end_text();
3001   reset_selection();
3002   
3003   pg = ui.cur_page;
3004   for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
3005     if (ui.bg_apply_all_pages) pg = (struct Page *)pglist->data;
3006     prepare_new_undo();
3007     if (ui.bg_apply_all_pages) {
3008       if (pglist->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
3009       if (pglist->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
3010     }
3011     undo->type = ITEM_NEW_BG_RESIZE;
3012     undo->page = pg;
3013     undo->bg = pg->bg;
3014     undo->val_x = pg->width;
3015     undo->val_y = pg->height; 
3016     pg->bg = (struct Background *)g_memdup(ui.default_page.bg, sizeof(struct Background));
3017     pg->width = ui.default_page.width;
3018     pg->height = ui.default_page.height;
3019     pg->bg->canvas_item = undo->bg->canvas_item;
3020     undo->bg->canvas_item = NULL;
3021   
3022     make_page_clipbox(pg);
3023     update_canvas_bg(pg);
3024     if (!ui.bg_apply_all_pages) break;
3025   }
3026   do_switch_page(ui.pageno, TRUE, TRUE);
3027 }
3028
3029
3030 void
3031 on_journalSetAsDefault_activate        (GtkMenuItem     *menuitem,
3032                                         gpointer         user_data)
3033 {
3034   if (ui.cur_page->bg->type != BG_SOLID) return;
3035   
3036   end_text();
3037   prepare_new_undo();
3038   undo->type = ITEM_NEW_DEFAULT_BG;
3039   undo->val_x = ui.default_page.width;
3040   undo->val_y = ui.default_page.height;
3041   undo->bg = ui.default_page.bg;
3042   
3043   ui.default_page.width = ui.cur_page->width;
3044   ui.default_page.height = ui.cur_page->height;
3045   ui.default_page.bg = (struct Background *)g_memdup(ui.cur_page->bg, sizeof(struct Background));
3046   ui.default_page.bg->canvas_item = NULL;
3047 }
3048
3049
3050 void
3051 on_comboStdSizes_changed               (GtkComboBox     *combobox,
3052                                         gpointer         user_data)
3053 {
3054   GtkEntry *entry;
3055   GtkComboBox *comboUnit;
3056   int val;
3057   gchar text[20];
3058
3059   if (papersize_need_init) {
3060     gtk_combo_box_set_active(combobox, papersize_std);
3061     papersize_need_init = FALSE;
3062   } else {
3063     val = gtk_combo_box_get_active(combobox);
3064     if (val == -1 || val == papersize_std) return;
3065     papersize_std = val;
3066     if (val == STD_SIZE_CUSTOM) return;
3067     papersize_unit = std_units[val];
3068     papersize_width = std_widths[val];
3069     papersize_height = std_heights[val];
3070   }
3071   comboUnit = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboUnit"));
3072   gtk_combo_box_set_active(comboUnit, papersize_unit);
3073   entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryWidth"));
3074   g_snprintf(text, 20, "%.2f", papersize_width/unit_sizes[papersize_unit]);
3075   if (g_str_has_suffix(text, ".00")) 
3076     g_snprintf(text, 20, "%d", (int) (papersize_width/unit_sizes[papersize_unit]));
3077   gtk_entry_set_text(entry, text);
3078   entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryHeight"));
3079   g_snprintf(text, 20, "%.2f", papersize_height/unit_sizes[papersize_unit]);
3080   if (g_str_has_suffix(text, ".00")) 
3081     g_snprintf(text, 20, "%d", (int) (papersize_height/unit_sizes[papersize_unit]));
3082   gtk_entry_set_text(entry, text);
3083 }
3084
3085
3086 void
3087 on_entryWidth_changed                  (GtkEditable     *editable,
3088                                         gpointer         user_data)
3089 {
3090   double val;
3091   const gchar *text;
3092   gchar *ptr;
3093   GtkComboBox *comboStdSizes;
3094   
3095   text = gtk_entry_get_text(GTK_ENTRY(editable));
3096   val = strtod(text, &ptr);
3097   papersize_width_valid = (*ptr == 0 && val > 0.);
3098   if (!papersize_width_valid) return; // invalid entry
3099   val *= unit_sizes[papersize_unit];
3100   if (fabs(val - papersize_width) < 0.1) return; // no change
3101   papersize_std = STD_SIZE_CUSTOM;
3102   papersize_width = val;
3103   comboStdSizes = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboStdSizes"));
3104   gtk_combo_box_set_active(comboStdSizes, papersize_std);
3105 }
3106
3107
3108 void
3109 on_entryHeight_changed                 (GtkEditable     *editable,
3110                                         gpointer         user_data)
3111 {
3112   double val;
3113   const gchar *text;
3114   gchar *ptr;
3115   GtkComboBox *comboStdSizes;
3116   
3117   text = gtk_entry_get_text(GTK_ENTRY(editable));
3118   val = strtod(text, &ptr);
3119   papersize_height_valid = (*ptr == 0 && val > 0.);
3120   if (!papersize_height_valid) return; // invalid entry
3121   val *= unit_sizes[papersize_unit];
3122   if (fabs(val - papersize_height) < 0.1) return; // no change
3123   papersize_std = STD_SIZE_CUSTOM;
3124   papersize_height = val;
3125   comboStdSizes = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboStdSizes"));
3126   gtk_combo_box_set_active(comboStdSizes, papersize_std);
3127 }
3128
3129
3130 void
3131 on_comboUnit_changed                   (GtkComboBox     *combobox,
3132                                         gpointer         user_data)
3133 {
3134   GtkEntry *entry;
3135   int val;
3136   gchar text[20];
3137
3138   val = gtk_combo_box_get_active(combobox);
3139   if (val == -1 || val == papersize_unit) return;
3140   papersize_unit = val;
3141   entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryWidth"));
3142   if (papersize_width_valid) {
3143     g_snprintf(text, 20, "%.2f", papersize_width/unit_sizes[papersize_unit]);
3144     if (g_str_has_suffix(text, ".00")) 
3145       g_snprintf(text, 20, "%d", (int) (papersize_width/unit_sizes[papersize_unit]));
3146   } else *text = 0;
3147   gtk_entry_set_text(entry, text);
3148   if (papersize_height_valid) {
3149     entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryHeight"));
3150     g_snprintf(text, 20, "%.2f", papersize_height/unit_sizes[papersize_unit]);
3151     if (g_str_has_suffix(text, ".00")) 
3152       g_snprintf(text, 20, "%d", (int) (papersize_height/unit_sizes[papersize_unit]));
3153   } else *text = 0;
3154   gtk_entry_set_text(entry, text);
3155 }
3156
3157
3158 void
3159 on_viewFullscreen_activate             (GtkMenuItem     *menuitem,
3160                                         gpointer         user_data)
3161 {
3162   gboolean active;
3163   
3164   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
3165     active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3166   else
3167     active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
3168
3169   if (active == ui.fullscreen) return;
3170   do_fullscreen(active);
3171 }
3172
3173
3174 void
3175 on_optionsButtonMappings_activate      (GtkMenuItem     *menuitem,
3176                                         gpointer         user_data)
3177 {
3178   end_text();
3179   ui.use_erasertip =
3180     gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3181   update_mappings_menu();
3182 }
3183
3184
3185 void
3186 on_optionsProgressiveBG_activate       (GtkMenuItem     *menuitem,
3187                                         gpointer         user_data)
3188 {
3189   gboolean active;
3190   
3191   active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3192   if (ui.progressive_bg == active) return;
3193   end_text();
3194   ui.progressive_bg = active;
3195   if (!ui.progressive_bg) rescale_bg_pixmaps();
3196 }
3197
3198
3199 void
3200 on_mru_activate                        (GtkMenuItem     *menuitem,
3201                                         gpointer         user_data)
3202 {
3203   int which;
3204   gboolean success;
3205   GtkWidget *dialog;
3206   
3207   end_text();
3208   if (!ok_to_close()) return; // user aborted on save confirmation
3209   
3210   for (which = 0 ; which < MRU_SIZE; which++) {
3211     if (ui.mrumenu[which] == GTK_WIDGET(menuitem)) break;
3212   }
3213   if (which == MRU_SIZE || ui.mru[which] == NULL) return; // not found...
3214
3215   set_cursor_busy(TRUE);
3216   success = open_journal(ui.mru[which]);
3217   set_cursor_busy(FALSE);
3218   if (success) return;
3219
3220   /* open failed */
3221   dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
3222     GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening file '%s'"), ui.mru[which]);
3223   gtk_dialog_run(GTK_DIALOG(dialog));
3224   gtk_widget_destroy(dialog);
3225   delete_mru_entry(which);
3226 }
3227
3228
3229 void
3230 on_button2Pen_activate                 (GtkMenuItem     *menuitem,
3231                                         gpointer         user_data)
3232 {
3233   process_mapping_activate(menuitem, 1, TOOL_PEN);
3234 }
3235
3236
3237 void
3238 on_button2Eraser_activate              (GtkMenuItem     *menuitem,
3239                                         gpointer         user_data)
3240 {
3241   process_mapping_activate(menuitem, 1, TOOL_ERASER);
3242 }
3243
3244
3245 void
3246 on_button2Highlighter_activate         (GtkMenuItem     *menuitem,
3247                                         gpointer         user_data)
3248 {
3249   process_mapping_activate(menuitem, 1, TOOL_HIGHLIGHTER);
3250 }
3251
3252
3253 void
3254 on_button2Text_activate                (GtkMenuItem     *menuitem,
3255                                         gpointer         user_data)
3256 {
3257   process_mapping_activate(menuitem, 1, TOOL_TEXT);
3258 }
3259
3260
3261 void
3262 on_button2Image_activate               (GtkMenuItem     *menuitem,
3263                                         gpointer         user_data)
3264 {
3265   process_mapping_activate(menuitem, 1, TOOL_IMAGE);
3266 }
3267
3268
3269 void
3270 on_button2SelectRegion_activate        (GtkMenuItem     *menuitem,
3271                                         gpointer         user_data)
3272 {
3273   process_mapping_activate(menuitem, 1, TOOL_SELECTREGION);
3274 }
3275
3276
3277 void
3278 on_button2SelectRectangle_activate     (GtkMenuItem     *menuitem,
3279                                         gpointer         user_data)
3280 {
3281   process_mapping_activate(menuitem, 1, TOOL_SELECTRECT);
3282 }
3283
3284
3285 void
3286 on_button2VerticalSpace_activate       (GtkMenuItem     *menuitem,
3287                                         gpointer         user_data)
3288 {
3289   process_mapping_activate(menuitem, 1, TOOL_VERTSPACE);
3290 }
3291
3292
3293 void
3294 on_button2LinkBrush_activate           (GtkMenuItem     *menuitem,
3295                                         gpointer         user_data)
3296 {
3297   int i;
3298   
3299   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3300   end_text();
3301   ui.linked_brush[1] = BRUSH_LINKED;
3302   for (i=0;i<NUM_STROKE_TOOLS;i++) update_mapping_linkings(i);
3303 }
3304
3305
3306 void
3307 on_button2CopyBrush_activate           (GtkMenuItem     *menuitem,
3308                                         gpointer         user_data)
3309 {
3310   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3311   end_text();
3312   if (ui.toolno[1] >= NUM_STROKE_TOOLS) {
3313     ui.linked_brush[1] = BRUSH_STATIC;
3314     update_mappings_menu_linkings();
3315     return;
3316   }
3317   ui.linked_brush[1] = BRUSH_COPIED;
3318   g_memmove(&(ui.brushes[1][ui.toolno[1]]), &(ui.brushes[0][ui.toolno[1]]), sizeof(struct Brush));
3319 }
3320
3321
3322 void
3323 on_button3Pen_activate                 (GtkMenuItem     *menuitem,
3324                                         gpointer         user_data)
3325 {
3326   process_mapping_activate(menuitem, 2, TOOL_PEN);
3327 }
3328
3329
3330 void
3331 on_button3Eraser_activate              (GtkMenuItem     *menuitem,
3332                                         gpointer         user_data)
3333 {
3334   process_mapping_activate(menuitem, 2, TOOL_ERASER);
3335 }
3336
3337
3338 void
3339 on_button3Highlighter_activate         (GtkMenuItem     *menuitem,
3340                                         gpointer         user_data)
3341 {
3342   process_mapping_activate(menuitem, 2, TOOL_HIGHLIGHTER);
3343 }
3344
3345
3346 void
3347 on_button3Text_activate                (GtkMenuItem     *menuitem,
3348                                         gpointer         user_data)
3349 {
3350   process_mapping_activate(menuitem, 2, TOOL_TEXT);
3351 }
3352
3353
3354 void
3355 on_button3Image_activate               (GtkMenuItem     *menuitem,
3356                                         gpointer         user_data)
3357 {
3358   process_mapping_activate(menuitem, 2, TOOL_IMAGE);
3359 }
3360
3361
3362 void
3363 on_button3SelectRegion_activate        (GtkMenuItem     *menuitem,
3364                                         gpointer         user_data)
3365 {
3366   process_mapping_activate(menuitem, 2, TOOL_SELECTREGION);
3367 }
3368
3369
3370 void
3371 on_button3SelectRectangle_activate     (GtkMenuItem     *menuitem,
3372                                         gpointer         user_data)
3373 {
3374   process_mapping_activate(menuitem, 2, TOOL_SELECTRECT);
3375 }
3376
3377
3378 void
3379 on_button3VerticalSpace_activate       (GtkMenuItem     *menuitem,
3380                                         gpointer         user_data)
3381 {
3382   process_mapping_activate(menuitem, 2, TOOL_VERTSPACE);
3383 }
3384
3385
3386 void
3387 on_button3LinkBrush_activate           (GtkMenuItem     *menuitem,
3388                                         gpointer         user_data)
3389 {
3390   int i;
3391   
3392   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3393   end_text();
3394   ui.linked_brush[2] = BRUSH_LINKED;
3395   for (i=0;i<NUM_STROKE_TOOLS;i++) update_mapping_linkings(i);
3396 }
3397
3398
3399 void
3400 on_button3CopyBrush_activate           (GtkMenuItem     *menuitem,
3401                                         gpointer         user_data)
3402 {
3403   if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3404   end_text();
3405   if (ui.toolno[2] >= NUM_STROKE_TOOLS) {
3406     ui.linked_brush[2] = BRUSH_STATIC;
3407     update_mappings_menu_linkings();
3408     return;
3409   }
3410   ui.linked_brush[2] = BRUSH_COPIED;
3411   g_memmove(&(ui.brushes[2][ui.toolno[2]]), &(ui.brushes[0][ui.toolno[2]]), sizeof(struct Brush));
3412 }
3413
3414 // the set zoom dialog
3415
3416 GtkWidget *zoom_dialog;
3417 double zoom_percent;
3418
3419 void
3420 on_viewSetZoom_activate                (GtkMenuItem     *menuitem,
3421                                         gpointer         user_data)
3422 {
3423   int response;
3424   double test_w, test_h;
3425   GtkSpinButton *spinZoom;
3426   
3427   end_text();
3428   zoom_dialog = create_zoomDialog();
3429   zoom_percent = 100*ui.zoom / DEFAULT_ZOOM;
3430   spinZoom = GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(zoom_dialog), "spinZoom"));
3431   gtk_spin_button_set_increments(spinZoom, ui.zoom_step_increment, 5*ui.zoom_step_increment);
3432   gtk_spin_button_set_value(spinZoom, zoom_percent);
3433   test_w = 100*(GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width/DEFAULT_ZOOM;
3434   test_h = 100*(GTK_WIDGET(canvas))->allocation.height/ui.cur_page->height/DEFAULT_ZOOM;
3435   if (zoom_percent > 99.9 && zoom_percent < 100.1) 
3436     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3437            G_OBJECT(zoom_dialog), "radioZoom100")), TRUE);
3438   else if (zoom_percent > test_w-0.1 && zoom_percent < test_w+0.1)
3439     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3440            G_OBJECT(zoom_dialog), "radioZoomWidth")), TRUE);
3441   else if (zoom_percent > test_h-0.1 && zoom_percent < test_h+0.1)
3442     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3443            G_OBJECT(zoom_dialog), "radioZoomHeight")), TRUE);
3444   else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3445            G_OBJECT(zoom_dialog), "radioZoom")), TRUE);
3446   gtk_widget_show(zoom_dialog);
3447   
3448   do {
3449     response = gtk_dialog_run(GTK_DIALOG(zoom_dialog));
3450     if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY) {
3451       ui.zoom = DEFAULT_ZOOM*zoom_percent/100;
3452       gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
3453       rescale_text_items();
3454       rescale_bg_pixmaps();
3455       rescale_images();
3456     }
3457   } while (response == GTK_RESPONSE_APPLY);
3458   
3459   gtk_widget_destroy(zoom_dialog);
3460 }
3461
3462
3463 void
3464 on_spinZoom_value_changed              (GtkSpinButton   *spinbutton,
3465                                         gpointer         user_data)
3466 {
3467   double val;
3468
3469   val = gtk_spin_button_get_value(GTK_SPIN_BUTTON(g_object_get_data(
3470              G_OBJECT(zoom_dialog), "spinZoom")));
3471   if (val<1) return;
3472   if (val<10) val=10.;
3473   if (val>1500) val=1500.;
3474   if (val<zoom_percent-1 || val>zoom_percent+1)
3475     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3476            G_OBJECT(zoom_dialog), "radioZoom")), TRUE);
3477   zoom_percent = val;
3478 }
3479
3480
3481 void
3482 on_radioZoom_toggled                   (GtkToggleButton *togglebutton,
3483                                         gpointer         user_data)
3484 {
3485   // nothing to do
3486 }
3487
3488
3489 void
3490 on_radioZoom100_toggled                (GtkToggleButton *togglebutton,
3491                                         gpointer         user_data)
3492 {
3493   if (!gtk_toggle_button_get_active(togglebutton)) return;
3494   zoom_percent = 100.;
3495   gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3496         G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3497 }
3498
3499
3500 void
3501 on_radioZoomWidth_toggled              (GtkToggleButton *togglebutton,
3502                                         gpointer         user_data)
3503 {
3504   if (!gtk_toggle_button_get_active(togglebutton)) return;
3505   zoom_percent = 100*(GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width/DEFAULT_ZOOM;
3506   gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3507         G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3508 }
3509
3510
3511 void
3512 on_radioZoomHeight_toggled             (GtkToggleButton *togglebutton,
3513                                         gpointer         user_data)
3514 {
3515   if (!gtk_toggle_button_get_active(togglebutton)) return;
3516   zoom_percent = 100*(GTK_WIDGET(canvas))->allocation.height/ui.cur_page->height/DEFAULT_ZOOM;
3517   gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3518         G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3519 }
3520
3521
3522 void
3523 on_toolsHand_activate                  (GtkMenuItem     *menuitem,
3524                                         gpointer         user_data)
3525 {
3526   if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
3527     if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
3528       return;
3529   } else {
3530     if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
3531       return;
3532   }
3533
3534   if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
3535   if (ui.toolno[ui.cur_mapping] == TOOL_HAND) return;
3536
3537   ui.cur_mapping = 0;
3538   end_text();
3539   reset_selection();
3540   ui.toolno[ui.cur_mapping] = TOOL_HAND;
3541   update_mapping_linkings(-1);
3542   update_tool_buttons();
3543   update_tool_menu();
3544   update_color_menu();
3545   update_cursor();
3546 }
3547
3548
3549 void
3550 on_button2Hand_activate                (GtkMenuItem     *menuitem,
3551                                         gpointer         user_data)
3552 {
3553   process_mapping_activate(menuitem, 1, TOOL_HAND);
3554 }
3555
3556
3557 void
3558 on_button3Hand_activate                (GtkMenuItem     *menuitem,
3559                                         gpointer         user_data)
3560 {
3561   process_mapping_activate(menuitem, 2, TOOL_HAND);
3562 }
3563
3564
3565 void
3566 on_optionsPrintRuling_activate         (GtkMenuItem     *menuitem,
3567                                         gpointer         user_data)
3568 {
3569   end_text();
3570   ui.print_ruling = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3571 }
3572
3573 void
3574 on_optionsAutoloadPdfXoj_activate      (GtkMenuItem     *menuitem,
3575                                         gpointer         user_data)
3576 {
3577   end_text();
3578   ui.autoload_pdf_xoj = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3579 }
3580
3581 void
3582 on_fontButton_font_set                 (GtkFontButton   *fontbutton,
3583                                         gpointer         user_data)
3584 {
3585   gchar *str;
3586   
3587   str = g_strdup(gtk_font_button_get_font_name(fontbutton));
3588   process_font_sel(str);
3589 }
3590
3591 void
3592 on_optionsLeftHanded_activate          (GtkMenuItem     *menuitem,   
3593                                         gpointer         user_data)
3594 {
3595   end_text();
3596   ui.left_handed = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3597   gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW(GET_COMPONENT("scrolledwindowMain")),
3598     ui.left_handed?GTK_CORNER_TOP_RIGHT:GTK_CORNER_TOP_LEFT);
3599 }
3600
3601 void
3602 on_optionsShortenMenus_activate        (GtkMenuItem     *menuitem,  
3603                                         gpointer         user_data)
3604 {
3605   gchar *item, *nextptr;
3606   GtkWidget *w;
3607   
3608   end_text();
3609   ui.shorten_menus = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3610   
3611   /* go over the item list */
3612   item = ui.shorten_menu_items;
3613   while (*item==' ') item++;
3614   while (*item) {
3615     nextptr = strchr(item, ' ');
3616     if (nextptr!=NULL) *nextptr = 0;
3617     // hide or show the item
3618     w = GET_COMPONENT(item);
3619     if (w != NULL) {
3620       if (ui.shorten_menus) gtk_widget_hide(w);
3621       else gtk_widget_show(w);
3622     }
3623     // next item
3624     if (nextptr==NULL) break;
3625     *nextptr = ' ';
3626     item = nextptr;
3627     while (*item==' ') item++;
3628   }
3629   
3630   // just in case someone tried to unhide stuff they shouldn't be seeing
3631   hide_unimplemented();
3632   // maybe we should also make sure the drawing area stays visible ?
3633 }
3634
3635 void
3636 on_optionsAutoSavePrefs_activate       (GtkMenuItem     *menuitem,  
3637                                         gpointer         user_data)
3638 {
3639   end_text();
3640   ui.auto_save_prefs = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3641 }
3642
3643 void
3644 on_optionsPressureSensitive_activate   (GtkMenuItem     *menuitem,
3645                                         gpointer         user_data)
3646 {
3647   int i;
3648   end_text();
3649   ui.pressure_sensitivity =
3650     gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3651   for (i=0; i<=NUM_BUTTONS; i++)
3652     ui.brushes[i][TOOL_PEN].variable_width = ui.pressure_sensitivity;
3653   update_mappings_menu();
3654 }
3655
3656
3657 void
3658 on_buttonColorChooser_set              (GtkColorButton  *colorbutton,
3659                                         gpointer         user_data)
3660 {
3661   GdkColor gdkcolor;
3662   guint16 alpha;
3663   
3664   gtk_color_button_get_color(colorbutton, &gdkcolor);
3665   alpha = gtk_color_button_get_alpha(colorbutton);
3666   process_color_activate((GtkMenuItem*)colorbutton, COLOR_OTHER, gdkcolor_to_rgba(gdkcolor, alpha));
3667 }
3668
3669
3670 void
3671 on_optionsButtonsSwitchMappings_activate(GtkMenuItem    *menuitem,
3672                                         gpointer         user_data)
3673 {
3674   end_text();
3675   switch_mapping(0);
3676   ui.button_switch_mapping = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3677 }
3678
3679