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