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