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