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