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