]> git.donarmstrong.com Git - xournal.git/commitdiff
Initial revision
authorauroux <auroux>
Sun, 29 Jan 2006 19:39:22 +0000 (19:39 +0000)
committerauroux <auroux>
Sun, 29 Jan 2006 19:39:22 +0000 (19:39 +0000)
src/xo-callbacks.c [new file with mode: 0644]

diff --git a/src/xo-callbacks.c b/src/xo-callbacks.c
new file mode 100644 (file)
index 0000000..f2e6e3f
--- /dev/null
@@ -0,0 +1,2504 @@
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <math.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <libgnomecanvas/libgnomecanvas.h>
+#include <time.h>
+#include <libgnomeprintui/gnome-print-dialog.h>
+#include <glib/gstdio.h>
+
+#include "xournal.h"
+#include "xo-callbacks.h"
+#include "xo-interface.h"
+#include "xo-support.h"
+#include "xo-misc.h"
+#include "xo-file.h"
+#include "xo-paint.h"
+#include "xo-print.h"
+
+void
+on_fileNew_activate                    (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (close_journal()) {
+    new_journal();
+    ui.zoom = DEFAULT_ZOOM;
+    update_page_stuff();
+    gtk_adjustment_set_value(gtk_layout_get_vadjustment(GTK_LAYOUT(canvas)), 0);
+    gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+  }
+}
+
+
+void
+on_fileNewBackground_activate          (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  GtkWidget *dialog, *attach_opt;
+  GtkFileFilter *filt_all, *filt_pdf;
+  char *filename;
+  int file_domain;
+  gboolean success;
+  
+  if (!ok_to_close()) return; // user aborted on save confirmation
+  
+  dialog = gtk_file_chooser_dialog_new("Open PDF", GTK_WINDOW (winMain),
+     GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+     GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
+     
+  filt_all = gtk_file_filter_new();
+  gtk_file_filter_set_name(filt_all, "All files");
+  gtk_file_filter_add_pattern(filt_all, "*");
+  filt_pdf = gtk_file_filter_new();
+  gtk_file_filter_set_name(filt_pdf, "PDF files");
+  gtk_file_filter_add_pattern(filt_pdf, "*.pdf");
+  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pdf);
+  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
+
+  attach_opt = gtk_check_button_new_with_label("Attach file to the journal");
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(attach_opt), FALSE);
+  gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER (dialog), attach_opt);
+  
+  if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
+    gtk_widget_destroy(dialog);
+    return;
+  }
+  filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(attach_opt)))
+       file_domain = DOMAIN_ATTACH;
+  else file_domain = DOMAIN_ABSOLUTE;
+  
+  gtk_widget_destroy(dialog);
+
+  set_cursor_busy(TRUE);
+  ui.saved = TRUE; // force close_journal to work
+  close_journal();
+  while (bgpdf.status != STATUS_NOT_INIT) {
+    // waiting for pdf processes to finish dying
+    gtk_main_iteration(); 
+  }
+  new_journal();
+  ui.zoom = DEFAULT_ZOOM;
+  gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+  update_page_stuff();
+  success = init_bgpdf(filename, TRUE, file_domain);
+  set_cursor_busy(FALSE);
+  if (success) {
+    g_free(filename);
+    return;
+  }
+  
+  /* open failed */
+  dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
+    GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Error opening file '%s'", filename);
+  gtk_dialog_run(GTK_DIALOG(dialog));
+  gtk_widget_destroy(dialog);
+  g_free(filename);
+}
+
+
+void
+on_fileOpen_activate                   (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  GtkWidget *dialog;
+  GtkFileFilter *filt_all, *filt_xoj;
+  char *filename;
+  gboolean success;
+  
+  if (!ok_to_close()) return; // user aborted on save confirmation
+  
+  dialog = gtk_file_chooser_dialog_new("Open Journal", GTK_WINDOW (winMain),
+     GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+     GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
+     
+  filt_all = gtk_file_filter_new();
+  gtk_file_filter_set_name(filt_all, "All files");
+  gtk_file_filter_add_pattern(filt_all, "*");
+  filt_xoj = gtk_file_filter_new();
+  gtk_file_filter_set_name(filt_xoj, "Xournal files");
+  gtk_file_filter_add_pattern(filt_xoj, "*.xoj");
+  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_xoj);
+  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
+  
+  if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
+    gtk_widget_destroy(dialog);
+    return;
+  }
+  filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+  gtk_widget_destroy(dialog);
+
+  set_cursor_busy(TRUE);
+  success = open_journal(filename);
+  set_cursor_busy(FALSE);
+  if (success) return;
+  
+  /* open failed */
+  dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
+    GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Error opening file '%s'", filename);
+  gtk_dialog_run(GTK_DIALOG(dialog));
+  gtk_widget_destroy(dialog);
+  g_free(filename);
+
+}
+
+
+void
+on_fileSave_activate                   (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  GtkWidget *dialog;
+  
+  if (ui.filename == NULL) {
+    on_fileSaveAs_activate(menuitem, user_data);
+    return;
+  }
+  set_cursor_busy(TRUE);
+  if (save_journal(ui.filename)) { // success
+    set_cursor_busy(FALSE);
+    ui.saved = TRUE;
+    return;
+  }
+  set_cursor_busy(FALSE);
+  /* save failed */
+  dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
+    GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Error saving file '%s'", ui.filename);
+  gtk_dialog_run(GTK_DIALOG(dialog));
+  gtk_widget_destroy(dialog);
+}
+
+
+void
+on_fileSaveAs_activate                 (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  GtkWidget *dialog, *warning_dialog;
+  GtkFileFilter *filt_all, *filt_xoj;
+  char *filename;
+  char stime[30];
+  time_t curtime;
+  gboolean warn;
+  struct stat stat_buf;
+  
+  dialog = gtk_file_chooser_dialog_new("Save Journal", GTK_WINDOW (winMain),
+     GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+     GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
+     
+  if (ui.filename!=NULL) {
+    if (ui.filename[0] == '/')
+      gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), ui.filename);
+    else
+      gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), ui.filename);
+  } else {
+    curtime = time(NULL);
+    strftime(stime, 30, "%F-Note-%H-%M.xoj", localtime(&curtime));
+    gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), stime);
+  }
+     
+  filt_all = gtk_file_filter_new();
+  gtk_file_filter_set_name(filt_all, "All files");
+  gtk_file_filter_add_pattern(filt_all, "*");
+  filt_xoj = gtk_file_filter_new();
+  gtk_file_filter_set_name(filt_xoj, "Xournal files");
+  gtk_file_filter_add_pattern(filt_xoj, "*.xoj");
+  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_xoj);
+  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
+  
+  // somehow this doesn't seem to be set by default
+  gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
+
+  do {
+    if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
+      gtk_widget_destroy(dialog);
+      return;
+    }
+    filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+    warn = g_file_test (filename, G_FILE_TEST_EXISTS);
+    if (warn) { // ok to overwrite an empty file
+      if (!g_stat(filename, &stat_buf))
+        if (stat_buf.st_size == 0) warn=FALSE;
+    }
+    if (warn && ui.filename!=NULL) { // ok to overwrite oneself
+      if (ui.filename[0]=='/' && !strcmp(ui.filename, filename)) warn=FALSE;
+      if (ui.filename[0]!='/' && g_str_has_suffix(filename, ui.filename)) warn=FALSE;
+    }
+    if (warn) {
+      warning_dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), 
+        GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
+        "Should the file %s be overwritten?", filename);
+      if (gtk_dialog_run(GTK_DIALOG(warning_dialog)) == GTK_RESPONSE_YES)
+        warn = FALSE;
+      gtk_widget_destroy(warning_dialog);
+    }
+  } while (warn);
+
+  gtk_widget_destroy(dialog);
+
+  set_cursor_busy(TRUE);
+  if (save_journal(filename)) { // success
+    ui.saved = TRUE;
+    set_cursor_busy(FALSE);
+    update_file_name(filename);
+    return;
+  }
+  set_cursor_busy(FALSE);
+  /* save failed */
+  dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
+    GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Error saving file '%s'", filename);
+  gtk_dialog_run(GTK_DIALOG(dialog));
+  gtk_widget_destroy(dialog);
+  g_free(filename);
+}
+
+
+void
+on_filePrintOptions_activate           (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_filePrint_activate                  (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  GtkWidget *printDialog, *preview;
+  GnomePrintJob *gpj;
+  int fromPage, toPage;
+  int response;
+  char *in_fn;
+  guchar *s;
+  GnomePrintConfig *config = gnome_print_config_default();
+
+  if (ui.filename!=NULL) {
+    if (g_str_has_suffix(ui.filename, ".xoj")) {
+      in_fn = g_strdup(ui.filename);
+      g_strlcpy(g_strrstr(in_fn, "xoj"), "pdf", 4);
+    } 
+    else
+      in_fn = g_strdup_printf("%s.pdf", ui.filename);
+    gnome_print_config_set(config, (guchar *)"Printer", (guchar *)"PDF");
+    gnome_print_config_set(config, (guchar *)GNOME_PRINT_KEY_OUTPUT_FILENAME, (guchar *)in_fn);
+    gnome_print_config_set(config, (guchar *)"Settings.Transport.Backend.FileName", (guchar *)in_fn);
+    g_strlcpy(g_strrstr(in_fn, "pdf"), "ps", 3);
+    gnome_print_config_set(config, (guchar *)"Printer", (guchar *)"GENERIC");
+    gnome_print_config_set (config, (guchar *)GNOME_PRINT_KEY_OUTPUT_FILENAME, (guchar *)in_fn);
+    s = gnome_print_config_get(config, (guchar *)"Settings.Transport.Backend.FileName");
+    if (s != NULL) {
+      g_free(s);
+      gnome_print_config_set(config, (guchar *)"Settings.Transport.Backend.FileName", (guchar *)in_fn);
+    }
+    g_free(in_fn);
+  }
+  
+  gpj = gnome_print_job_new(config); /* was NULL */
+  gnome_print_config_unref(config);
+/* end */
+  printDialog = gnome_print_dialog_new(gpj, (guchar *)"Print", GNOME_PRINT_DIALOG_RANGE);
+  gnome_print_dialog_construct_range_page(GNOME_PRINT_DIALOG(printDialog),
+    GNOME_PRINT_RANGE_ALL | GNOME_PRINT_RANGE_RANGE,
+    1, journal.npages, (guchar *)"Current page", (guchar *)"Pages");
+  /* don't have "Current page" as option, else it becomes the default!! */
+  
+  gtk_dialog_set_response_sensitive(GTK_DIALOG(printDialog),
+                         GNOME_PRINT_DIALOG_RESPONSE_PREVIEW, FALSE);
+  /* the print-job-preview "feature" is completely, hopelessly broken */                       
+
+  response = gtk_dialog_run(GTK_DIALOG(printDialog));
+  if (response <= 0) {
+    gtk_widget_destroy(printDialog);
+    return;
+  }
+
+/*
+  if (response == GNOME_PRINT_DIALOG_RESPONSE_PREVIEW) {
+    print_job_render(gpj, 0, journal.npages-1);
+    gtk_widget_destroy(printDialog);
+    preview = gnome_print_job_preview_new(gpj, (guchar *)"Preview");
+    try_fix_print_preview_ui(preview);
+    gtk_window_set_modal(GTK_WINDOW(preview), TRUE);
+    gtk_widget_show_all(preview);
+  }
+*/
+
+  if (response == GNOME_PRINT_DIALOG_RESPONSE_PRINT) {
+    switch(gnome_print_dialog_get_range(GNOME_PRINT_DIALOG(printDialog))) {
+      case GNOME_PRINT_RANGE_RANGE: 
+        gnome_print_dialog_get_range_page(GNOME_PRINT_DIALOG(printDialog), &fromPage, &toPage);
+        break;
+      default: 
+        fromPage = 0; 
+        toPage = journal.npages-1;
+    }
+
+    gtk_widget_destroy(printDialog);
+    print_job_render(gpj, fromPage, toPage);
+  }
+}
+
+
+void
+on_filePrintPDF_activate               (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+  GtkWidget *dialog;
+  GtkFileFilter *filt_all, *filt_pdf;
+  char *filename, *in_fn;
+  char stime[30];
+  time_t curtime;
+  GnomePrintJob *gpj;
+  GnomePrintConfig *config;
+
+  
+  dialog = gtk_file_chooser_dialog_new("Print to PDF", GTK_WINDOW (winMain),
+     GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+     GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
+     
+  if (ui.filename!=NULL) {
+    if (g_str_has_suffix(ui.filename, ".xoj")) {
+      in_fn = g_strdup(ui.filename);
+      g_strlcpy(g_strrstr(in_fn, "xoj"), "pdf", 4);
+    } 
+    else
+      in_fn = g_strdup_printf("%s.pdf", ui.filename);
+    if (in_fn[0] == '/')
+      gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), in_fn);
+    gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), in_fn);
+  } else {
+    curtime = time(NULL);
+    strftime(stime, 30, "%F-Note-%H-%M.pdf", localtime(&curtime));
+    gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), stime);
+    in_fn = NULL;
+  }
+     
+  filt_all = gtk_file_filter_new();
+  gtk_file_filter_set_name(filt_all, "All files");
+  gtk_file_filter_add_pattern(filt_all, "*");
+  filt_pdf = gtk_file_filter_new();
+  gtk_file_filter_set_name(filt_pdf, "PDF files");
+  gtk_file_filter_add_pattern(filt_pdf, "*.pdf");
+  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pdf);
+  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
+  
+  // somehow this doesn't seem to be set by default
+  gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
+
+  if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
+    g_free(in_fn);
+    gtk_widget_destroy(dialog);
+    return;
+  }
+  filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+  g_free(in_fn);
+  gtk_widget_destroy(dialog);
+  
+  config = gnome_print_config_default();
+  gnome_print_config_set(config, (guchar *)"Printer", (guchar *)"PDF");
+  gpj = gnome_print_job_new(config);
+  gnome_print_job_print_to_file(gpj, filename);
+  
+  print_job_render(gpj, 0, journal.npages-1);
+  gnome_print_config_unref(config);
+
+  g_free(filename);
+}
+
+
+void
+on_fileQuit_activate                   (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (ok_to_close()) gtk_main_quit ();
+}
+
+
+void
+on_editUndo_activate                   (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  struct UndoItem *u;
+  GList *list, *itemlist;
+  struct UndoErasureData *erasure;
+  struct Item *it;
+  struct Background *tmp_bg;
+  double tmp_x, tmp_y;
+  
+  if (undo == NULL) return; // nothing to undo!
+  reset_selection(); // safer
+  if (undo->type == ITEM_STROKE) {
+    // we're keeping the stroke info, but deleting the canvas item
+    gtk_object_destroy(GTK_OBJECT(undo->item->canvas_item));
+    undo->item->canvas_item = NULL;
+    // we also remove the object from its layer!
+    undo->layer->items = g_list_remove(undo->layer->items, undo->item);
+    undo->layer->nitems--;
+  }
+  else if (undo->type == ITEM_ERASURE) {
+    for (list = undo->erasurelist; list!=NULL; list = list->next) {
+      erasure = (struct UndoErasureData *)list->data;
+      // delete all the created items
+      for (itemlist = erasure->replacement_items; itemlist!=NULL; itemlist = itemlist->next) {
+        it = (struct Item *)itemlist->data;
+        gtk_object_destroy(GTK_OBJECT(it->canvas_item));
+        it->canvas_item = NULL;
+        undo->layer->items = g_list_remove(undo->layer->items, it);
+        undo->layer->nitems--;
+      }
+      // recreate the deleted one
+      erasure->item->canvas_item = gnome_canvas_item_new(undo->layer->group,
+             gnome_canvas_line_get_type(), "points", erasure->item->path,
+             "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND,
+             "fill-color-rgba", erasure->item->brush.color_rgba,
+             "width-units", erasure->item->brush.thickness, NULL);
+      undo->layer->items = g_list_insert(undo->layer->items, erasure->item,
+                                                             erasure->npos);
+      if (erasure->npos == 0)
+        lower_canvas_item_to(undo->layer->group, erasure->item->canvas_item, NULL);
+      else
+        lower_canvas_item_to(undo->layer->group, erasure->item->canvas_item,
+          ((struct Item *)g_list_nth_data(undo->layer->items, erasure->npos-1))->canvas_item);
+      undo->layer->nitems++;
+    }
+  }
+  else if (undo->type == ITEM_NEW_BG_ONE || undo->type == ITEM_NEW_BG_RESIZE
+           || undo->type == ITEM_PAPER_RESIZE) {
+    if (undo->type != ITEM_PAPER_RESIZE) {
+      // swap the two bg's
+      tmp_bg = undo->page->bg;
+      undo->page->bg = undo->bg;
+      undo->bg = tmp_bg;
+      undo->page->bg->canvas_item = undo->bg->canvas_item;
+      undo->bg->canvas_item = NULL;
+    }
+    if (undo->type != ITEM_NEW_BG_ONE) {
+      tmp_x = undo->page->width;
+      tmp_y = undo->page->height;
+      undo->page->width = undo->val_x;
+      undo->page->height = undo->val_y;
+      undo->val_x = tmp_x;
+      undo->val_y = tmp_y;
+      make_page_clipbox(undo->page);
+    }
+    update_canvas_bg(undo->page);
+    do_switch_page(g_list_index(journal.pages, undo->page), TRUE);
+  }
+  else if (undo->type == ITEM_NEW_DEFAULT_BG) {
+    tmp_bg = ui.default_page.bg;
+    ui.default_page.bg = undo->bg;
+    undo->bg = tmp_bg;
+    tmp_x = ui.default_page.width;
+    tmp_y = ui.default_page.height;
+    ui.default_page.width = undo->val_x;
+    ui.default_page.height = undo->val_y;
+    undo->val_x = tmp_x;
+    undo->val_y = tmp_y;
+  }
+  else if (undo->type == ITEM_NEW_PAGE) {
+    // unmap the page; keep the page & its empty layer in memory
+    if (undo->page->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->page->group));
+      // also destroys the background and layer's canvas items
+    undo->page->group = NULL;
+    undo->page->bg->canvas_item = NULL;
+    journal.pages = g_list_remove(journal.pages, undo->page);
+    journal.npages--;
+    if (ui.cur_page == undo->page) ui.cur_page = NULL;
+        // so do_switch_page() won't try to remap the layers of the defunct page
+    if (ui.pageno >= undo->val) ui.pageno--;
+    if (ui.pageno < 0) ui.pageno = 0;
+    do_switch_page(ui.pageno, TRUE);
+  }
+  else if (undo->type == ITEM_DELETE_PAGE) {
+    journal.pages = g_list_insert(journal.pages, undo->page, undo->val);
+    journal.npages++;
+    make_canvas_items(); // re-create the canvas items
+    do_switch_page(undo->val, TRUE);
+  }
+  else if (undo->type == ITEM_MOVESEL) {
+    for (itemlist = undo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
+      it = (struct Item *)itemlist->data;
+      if (it->canvas_item != NULL)
+        gnome_canvas_item_move(it->canvas_item, -undo->val_x, -undo->val_y);
+    }
+    move_journal_items_by(undo->itemlist, -undo->val_x, -undo->val_y);
+  }
+  else if (undo->type == ITEM_PASTE) {
+    for (itemlist = undo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
+      it = (struct Item *)itemlist->data;
+      gtk_object_destroy(GTK_OBJECT(it->canvas_item));
+      it->canvas_item = NULL;
+      undo->layer->items = g_list_remove(undo->layer->items, it);
+      undo->layer->nitems--;
+    }
+  }
+  else if (undo->type == ITEM_NEW_LAYER) {
+    // unmap the layer; keep the empty layer in memory
+    if (undo->layer->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->layer->group));
+    undo->layer->group = NULL;
+    undo->page->layers = g_list_remove(undo->page->layers, undo->layer);
+    undo->page->nlayers--;
+    do_switch_page(ui.pageno, FALSE); // don't stay with bad cur_layer info
+  }
+  else if (undo->type == ITEM_DELETE_LAYER) {
+    // special case of -1: deleted the last layer, created a new one
+    if (undo->val == -1) {
+      if (undo->layer2->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->layer2->group));
+      undo->layer2->group = NULL;
+      undo->page->layers = g_list_remove(undo->page->layers, undo->layer2);
+      undo->page->nlayers--;
+    }
+    // re-map the layer
+    undo->layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
+      undo->page->group, gnome_canvas_group_get_type(), NULL);
+    lower_canvas_item_to(undo->page->group, GNOME_CANVAS_ITEM(undo->layer->group),
+      (undo->val >= 1) ? GNOME_CANVAS_ITEM(((struct Layer *)
+            g_list_nth_data(undo->page->layers, undo->val-1))->group) :
+            undo->page->bg->canvas_item);
+    undo->page->layers = g_list_insert(undo->page->layers, undo->layer,
+                                     (undo->val >= 0) ? undo->val:0);
+    undo->page->nlayers++;
+    
+    for (itemlist = undo->layer->items; itemlist!=NULL; itemlist = itemlist->next) {
+      it = (struct Item *)itemlist->data;
+      if (it->type == ITEM_STROKE) {
+        it->canvas_item = gnome_canvas_item_new(undo->layer->group,
+            gnome_canvas_line_get_type(), "points", it->path,
+            "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND,
+            "fill-color-rgba", it->brush.color_rgba,
+            "width-units", it->brush.thickness, NULL);
+      }
+    }
+    do_switch_page(ui.pageno, FALSE); // show the restored layer & others...
+  }
+  
+  // move item from undo to redo stack
+  u = undo;
+  undo = undo->next;
+  u->next = redo;
+  redo = u;
+  ui.saved = FALSE;
+  update_undo_redo_enabled();
+  if (u->multiop & MULTIOP_CONT_UNDO) on_editUndo_activate(NULL,NULL); // loop
+}
+
+
+void
+on_editRedo_activate                   (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  struct UndoItem *u;
+  GList *list, *itemlist, *target;
+  struct UndoErasureData *erasure;
+  struct Item *it;
+  struct Background *tmp_bg;
+  struct Layer *l;
+  double tmp_x, tmp_y;
+  
+  if (redo == NULL) return; // nothing to redo!
+  reset_selection(); // safer
+  if (redo->type == ITEM_STROKE) {
+    // re-create the canvas_item
+    redo->item->canvas_item = gnome_canvas_item_new(redo->layer->group,
+     gnome_canvas_line_get_type(), "points", redo->item->path,
+     "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND,
+     "fill-color-rgba", redo->item->brush.color_rgba,
+     "width-units", redo->item->brush.thickness, NULL);
+    // reinsert the item on its layer
+    redo->layer->items = g_list_append(redo->layer->items, redo->item);
+    redo->layer->nitems++;
+  }
+  else if (redo->type == ITEM_ERASURE) {
+    for (list = redo->erasurelist; list!=NULL; list = list->next) {
+      erasure = (struct UndoErasureData *)list->data;
+      target = g_list_find(redo->layer->items, erasure->item);
+      // re-create all the created items
+      for (itemlist = erasure->replacement_items; itemlist!=NULL; itemlist = itemlist->next) {
+        it = (struct Item *)itemlist->data;
+        it->canvas_item = gnome_canvas_item_new(redo->layer->group,
+             gnome_canvas_line_get_type(), "points", it->path,
+             "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND,
+             "fill-color-rgba", it->brush.color_rgba,
+             "width-units", it->brush.thickness, NULL);
+        redo->layer->items = g_list_insert_before(redo->layer->items, target, it);
+        redo->layer->nitems++;
+        lower_canvas_item_to(redo->layer->group, it->canvas_item, erasure->item->canvas_item);
+      }
+      // re-delete the deleted one
+      gtk_object_destroy(GTK_OBJECT(erasure->item->canvas_item));
+      erasure->item->canvas_item = NULL;
+      redo->layer->items = g_list_delete_link(redo->layer->items, target);
+      redo->layer->nitems--;
+    }
+  }
+  else if (redo->type == ITEM_NEW_BG_ONE || redo->type == ITEM_NEW_BG_RESIZE
+           || redo->type == ITEM_PAPER_RESIZE) {
+    if (redo->type != ITEM_PAPER_RESIZE) {
+      // swap the two bg's
+      tmp_bg = redo->page->bg;
+      redo->page->bg = redo->bg;
+      redo->bg = tmp_bg;
+      redo->page->bg->canvas_item = redo->bg->canvas_item;
+      redo->bg->canvas_item = NULL;
+    }
+    if (redo->type != ITEM_NEW_BG_ONE) {
+      tmp_x = redo->page->width;
+      tmp_y = redo->page->height;
+      redo->page->width = redo->val_x;
+      redo->page->height = redo->val_y;
+      redo->val_x = tmp_x;
+      redo->val_y = tmp_y;
+      make_page_clipbox(redo->page);
+    }
+    update_canvas_bg(redo->page);
+    do_switch_page(g_list_index(journal.pages, redo->page), TRUE);
+  }
+  else if (redo->type == ITEM_NEW_DEFAULT_BG) {
+    tmp_bg = ui.default_page.bg;
+    ui.default_page.bg = redo->bg;
+    redo->bg = tmp_bg;
+    tmp_x = ui.default_page.width;
+    tmp_y = ui.default_page.height;
+    ui.default_page.width = redo->val_x;
+    ui.default_page.height = redo->val_y;
+    redo->val_x = tmp_x;
+    redo->val_y = tmp_y;
+  }
+  else if (redo->type == ITEM_NEW_PAGE) {
+    // remap the page
+    redo->page->bg->canvas_item = NULL;
+    redo->page->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
+      gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
+    make_page_clipbox(redo->page);
+    update_canvas_bg(redo->page);
+    l = (struct Layer *)redo->page->layers->data;
+    l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
+      redo->page->group, gnome_canvas_group_get_type(), NULL);
+    
+    journal.pages = g_list_insert(journal.pages, redo->page, redo->val);
+    journal.npages++;
+    do_switch_page(redo->val, TRUE);
+  }
+  else if (redo->type == ITEM_DELETE_PAGE) {
+    // unmap all the canvas items
+    gtk_object_destroy(GTK_OBJECT(redo->page->group));
+    redo->page->group = NULL;
+    redo->page->bg->canvas_item = NULL;
+    for (list = redo->page->layers; list!=NULL; list = list->next) {
+      l = (struct Layer *)list->data;
+      for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next)
+        ((struct Item *)itemlist->data)->canvas_item = NULL;
+      l->group = NULL;
+    }
+    journal.pages = g_list_remove(journal.pages, redo->page);
+    journal.npages--;
+    if (ui.pageno > undo->val || ui.pageno == journal.npages) ui.pageno--;
+    ui.cur_page = NULL;
+      // so do_switch_page() won't try to remap the layers of the defunct page
+    do_switch_page(ui.pageno, TRUE);
+  }
+  else if (redo->type == ITEM_MOVESEL) {
+    for (itemlist = redo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
+      it = (struct Item *)itemlist->data;
+      if (it->canvas_item != NULL)
+        gnome_canvas_item_move(it->canvas_item, redo->val_x, redo->val_y);
+    }
+    move_journal_items_by(redo->itemlist, redo->val_x, redo->val_y);
+  }
+  else if (redo->type == ITEM_PASTE) {
+    for (itemlist = redo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
+      it = (struct Item *)itemlist->data;
+      it->canvas_item = gnome_canvas_item_new(redo->layer->group,
+           gnome_canvas_line_get_type(), "points", it->path,
+           "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND,
+           "fill-color-rgba", it->brush.color_rgba,
+           "width-units", it->brush.thickness, NULL);
+      redo->layer->items = g_list_append(redo->layer->items, it);
+      redo->layer->nitems++;
+    }
+  }
+  else if (redo->type == ITEM_NEW_LAYER) {
+    redo->layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
+        redo->page->group, gnome_canvas_group_get_type(), NULL);
+    lower_canvas_item_to(redo->page->group, GNOME_CANVAS_ITEM(redo->layer->group),
+      (redo->val >= 1) ? GNOME_CANVAS_ITEM(((struct Layer *)
+            g_list_nth_data(redo->page->layers, redo->val-1))->group) :
+            redo->page->bg->canvas_item);
+    redo->page->layers = g_list_insert(redo->page->layers, redo->layer, redo->val);
+    redo->page->nlayers++;
+    do_switch_page(ui.pageno, FALSE);
+  }
+  else if (redo->type == ITEM_DELETE_LAYER) {
+    gtk_object_destroy(GTK_OBJECT(redo->layer->group));
+    redo->layer->group = NULL;
+    for (list=redo->layer->items; list!=NULL; list=list->next)
+      ((struct Item *)list->data)->canvas_item = NULL;
+    redo->page->layers = g_list_remove(redo->page->layers, redo->layer);
+    redo->page->nlayers--;
+    if (redo->val == -1) {
+      redo->layer2->group = (GnomeCanvasGroup *)gnome_canvas_item_new(
+        redo->page->group, gnome_canvas_group_get_type(), NULL);
+      redo->page->layers = g_list_append(redo->page->layers, redo->layer2);
+      redo->page->nlayers++;
+    }
+    do_switch_page(ui.pageno, FALSE);
+  }
+  
+  // move item from redo to undo stack
+  u = redo;
+  redo = redo->next;
+  u->next = undo;
+  undo = u;
+  ui.saved = FALSE;
+  update_undo_redo_enabled();
+  if (u->multiop & MULTIOP_CONT_REDO) on_editRedo_activate(NULL,NULL); // loop
+}
+
+
+void
+on_editCut_activate                    (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  selection_to_clip();
+  selection_delete();
+}
+
+
+void
+on_editCopy_activate                   (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  selection_to_clip();
+}
+
+
+void
+on_editPaste_activate                  (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  clipboard_paste();
+}
+
+
+void
+on_editDelete_activate                 (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  selection_delete();
+}
+
+
+void
+on_viewContinuous_activate             (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  GtkAdjustment *v_adj;
+  double yscroll;
+
+  if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
+  if (ui.view_continuous) return;
+  ui.view_continuous = TRUE;
+  v_adj = gtk_layout_get_vadjustment(GTK_LAYOUT(canvas));
+  yscroll = gtk_adjustment_get_value(v_adj) - ui.cur_page->voffset*ui.zoom;
+  update_page_stuff();
+  gtk_adjustment_set_value(v_adj, yscroll + ui.cur_page->voffset*ui.zoom);
+  // force a refresh
+  gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+}
+
+
+void
+on_viewOnePage_activate                (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  GtkAdjustment *v_adj;
+  double yscroll;
+  
+  if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
+  if (!ui.view_continuous) return;
+  ui.view_continuous = FALSE;
+  v_adj = gtk_layout_get_vadjustment(GTK_LAYOUT(canvas));
+  yscroll = gtk_adjustment_get_value(v_adj) - ui.cur_page->voffset*ui.zoom;
+  update_page_stuff();
+  gtk_adjustment_set_value(v_adj, yscroll + ui.cur_page->voffset*ui.zoom);
+  // force a refresh
+  gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+}
+
+
+void
+on_viewZoomIn_activate                 (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (ui.zoom > MAX_ZOOM) return;
+  ui.zoom *= 1.5;
+  gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+  rescale_bg_pixmaps();
+}
+
+
+void
+on_viewZoomOut_activate                (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (ui.zoom < MIN_ZOOM) return;
+  ui.zoom /= 1.5;
+  gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+  rescale_bg_pixmaps();
+}
+
+
+void
+on_viewNormalSize_activate             (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  ui.zoom = DEFAULT_ZOOM;
+  gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+  rescale_bg_pixmaps();
+}
+
+
+void
+on_viewPageWidth_activate              (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  ui.zoom = (GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width;
+  gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+  rescale_bg_pixmaps();
+}
+
+
+void
+on_viewFirstPage_activate              (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  do_switch_page(0, TRUE);
+}
+
+
+void
+on_viewPreviousPage_activate           (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (ui.pageno == 0) return;
+  do_switch_page(ui.pageno-1, TRUE);
+}
+
+
+void
+on_viewNextPage_activate               (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (ui.pageno == journal.npages-1) { // create a page at end
+    if (page_ops_forbidden()) return;
+    on_journalNewPageEnd_activate(menuitem, user_data);
+    return;
+  }
+  do_switch_page(ui.pageno+1, TRUE);
+}
+
+
+void
+on_viewLastPage_activate               (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  do_switch_page(journal.npages-1, TRUE);
+}
+
+
+void
+on_viewShowLayer_activate              (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (ui.layerno == ui.cur_page->nlayers-1) return;
+  reset_selection();
+  ui.layerno++;
+  ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
+  gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group));
+  update_page_stuff();
+}
+
+
+void
+on_viewHideLayer_activate              (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (ui.layerno == -1) return;
+  reset_selection();
+  gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group));
+  ui.layerno--;
+  if (ui.layerno<0) ui.cur_layer = NULL;
+  else ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
+  update_page_stuff();
+}
+
+
+void
+on_journalNewPageBefore_activate       (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  struct Page *pg;
+
+  if (page_ops_forbidden()) return;
+  reset_selection();
+  pg = new_page(ui.cur_page);
+  journal.pages = g_list_insert(journal.pages, pg, ui.pageno);
+  journal.npages++;
+  do_switch_page(ui.pageno, TRUE);
+  
+  prepare_new_undo();
+  undo->type = ITEM_NEW_PAGE;
+  undo->val = ui.pageno;
+  undo->page = pg;
+}
+
+
+void
+on_journalNewPageAfter_activate        (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  struct Page *pg;
+
+  if (page_ops_forbidden()) return;
+  reset_selection();
+  pg = new_page(ui.cur_page);
+  journal.pages = g_list_insert(journal.pages, pg, ui.pageno+1);
+  journal.npages++;
+  do_switch_page(ui.pageno+1, TRUE);
+
+  prepare_new_undo();
+  undo->type = ITEM_NEW_PAGE;
+  undo->val = ui.pageno;
+  undo->page = pg;
+}
+
+
+void
+on_journalNewPageEnd_activate          (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  struct Page *pg;
+
+  if (page_ops_forbidden()) return;
+  reset_selection();
+  pg = new_page((struct Page *)g_list_last(journal.pages)->data);
+  journal.pages = g_list_append(journal.pages, pg);
+  journal.npages++;
+  do_switch_page(journal.npages-1, TRUE);
+
+  prepare_new_undo();
+  undo->type = ITEM_NEW_PAGE;
+  undo->val = ui.pageno;
+  undo->page = pg;
+}
+
+
+void
+on_journalDeletePage_activate          (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  GList *layerlist, *itemlist;
+  struct Layer *l;
+
+  if (page_ops_forbidden()) return;
+  if (journal.npages == 1) return;
+  reset_selection();  
+  prepare_new_undo();
+  undo->type = ITEM_DELETE_PAGE;
+  undo->val = ui.pageno;
+  undo->page = ui.cur_page;
+
+  // unmap all the canvas items  
+  gtk_object_destroy(GTK_OBJECT(ui.cur_page->group));
+  ui.cur_page->group = NULL;
+  ui.cur_page->bg->canvas_item = NULL;
+  for (layerlist = ui.cur_page->layers; layerlist!=NULL; layerlist = layerlist->next) {
+    l = (struct Layer *)layerlist->data;
+    for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next)
+      ((struct Item *)itemlist->data)->canvas_item = NULL;
+    l->group = NULL;
+  }
+  
+  journal.pages = g_list_remove(journal.pages, ui.cur_page);
+  journal.npages--;
+  if (ui.pageno == journal.npages) ui.pageno--;
+  ui.cur_page = NULL;
+     // so do_switch_page() won't try to remap the layers of the defunct page
+  do_switch_page(ui.pageno, TRUE);
+}
+
+
+void
+on_journalNewLayer_activate            (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  struct Layer *l;
+  
+  reset_selection();
+  l = g_new(struct Layer, 1);
+  l->items = NULL;
+  l->nitems = 0;
+  l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
+    ui.cur_page->group, gnome_canvas_group_get_type(), NULL);
+  lower_canvas_item_to(ui.cur_page->group, GNOME_CANVAS_ITEM(l->group),
+    (ui.cur_layer!=NULL)?(GNOME_CANVAS_ITEM(ui.cur_layer->group)):(ui.cur_page->bg->canvas_item));
+  ui.cur_page->layers = g_list_insert(ui.cur_page->layers, l, ui.layerno+1);
+  ui.cur_layer = l;
+  ui.layerno++;
+  ui.cur_page->nlayers++;
+  update_page_stuff();
+
+  prepare_new_undo();
+  undo->type = ITEM_NEW_LAYER;
+  undo->val = ui.layerno;
+  undo->layer = l;
+  undo->page = ui.cur_page;  
+}
+
+
+void
+on_journalDeleteLayer_activate         (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  GList *list;
+  
+  if (ui.cur_layer == NULL) return;
+  reset_selection();
+  prepare_new_undo();
+  undo->type = ITEM_DELETE_LAYER;
+  undo->val = ui.layerno;
+  undo->layer = ui.cur_layer;
+  undo->layer2 = NULL;
+  undo->page = ui.cur_page;
+  // delete all the canvas items
+  gtk_object_destroy(GTK_OBJECT(ui.cur_layer->group));
+  ui.cur_layer->group = NULL;
+  for (list=ui.cur_layer->items; list!=NULL; list=list->next)
+    ((struct Item *)list->data)->canvas_item = NULL;
+
+  ui.cur_page->layers = g_list_remove(ui.cur_page->layers, ui.cur_layer);
+
+  if (ui.cur_page->nlayers>=2) {
+    ui.cur_page->nlayers--;
+    ui.layerno--;
+    if (ui.layerno<0) ui.cur_layer = NULL;
+    else ui.cur_layer = (struct Layer *)g_list_nth_data(ui.cur_page->layers, ui.layerno);
+  } 
+  else { // special case: can't remove the last layer
+    ui.cur_layer = g_new(struct Layer, 1);
+    ui.cur_layer->items = NULL;
+    ui.cur_layer->nitems = 0;
+    ui.cur_layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
+      ui.cur_page->group, gnome_canvas_group_get_type(), NULL);
+    ui.cur_page->layers = g_list_append(NULL, ui.cur_layer);
+    undo->val = -1;
+    undo->layer2 = ui.cur_layer;
+  }
+
+  update_page_stuff();
+}
+
+
+void
+on_journalFlatten_activate             (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+// the paper sizes dialog
+
+GtkWidget *papersize_dialog;
+int papersize_std, papersize_unit;
+double papersize_width, papersize_height;
+gboolean papersize_need_init, papersize_width_valid, papersize_height_valid;
+
+#define STD_SIZE_A4 0
+#define STD_SIZE_A4R 1
+#define STD_SIZE_LETTER 2
+#define STD_SIZE_LETTER_R 3
+#define STD_SIZE_CUSTOM 4
+
+#define UNIT_CM 0
+#define UNIT_IN 1
+#define UNIT_PX 2
+#define UNIT_PT 3
+
+double unit_sizes[4] = {28.346, 72., 1/DEFAULT_ZOOM, 1.};
+double std_widths[STD_SIZE_CUSTOM] =  {595.27, 841.89, 612., 792.};
+double std_heights[STD_SIZE_CUSTOM] = {841.89, 595.27, 792., 612.};
+double std_units[STD_SIZE_CUSTOM] = {UNIT_CM, UNIT_CM, UNIT_IN, UNIT_IN};
+
+void
+on_journalPaperSize_activate           (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  int i, response;
+  
+  papersize_dialog = create_papersizeDialog();
+  papersize_width = ui.cur_page->width;
+  papersize_height = ui.cur_page->height;
+  papersize_unit = UNIT_CM;
+//  if (ui.cur_page->bg->type == BG_PIXMAP) papersize_unit = UNIT_PX;
+  papersize_std = STD_SIZE_CUSTOM;
+  for (i=0;i<STD_SIZE_CUSTOM;i++)
+    if (fabs(papersize_width - std_widths[i])<0.1 &&
+        fabs(papersize_height - std_heights[i])<0.1)
+      { papersize_std = i; papersize_unit = std_units[i]; }
+  papersize_need_init = TRUE;
+  papersize_width_valid = papersize_height_valid = TRUE;
+      
+  gtk_widget_show(papersize_dialog);
+  on_comboStdSizes_changed(GTK_COMBO_BOX(g_object_get_data(
+       G_OBJECT(papersize_dialog), "comboStdSizes")), NULL);
+  gtk_dialog_set_default_response(GTK_DIALOG(papersize_dialog), GTK_RESPONSE_OK);
+       
+  response = gtk_dialog_run(GTK_DIALOG(papersize_dialog));
+  gtk_widget_destroy(papersize_dialog);
+  if (response != GTK_RESPONSE_OK) return;
+  
+  prepare_new_undo();
+  undo->type = ITEM_PAPER_RESIZE;
+  undo->page = ui.cur_page;
+  undo->val_x = ui.cur_page->width;
+  undo->val_y = ui.cur_page->height;
+
+  if (papersize_width_valid) ui.cur_page->width = papersize_width;
+  if (papersize_height_valid) ui.cur_page->height = papersize_height;
+
+  make_page_clipbox(ui.cur_page);
+  update_canvas_bg(ui.cur_page);
+  do_switch_page(ui.pageno, TRUE);
+}
+
+
+void
+on_papercolorWhite_activate            (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_papercolor_activate(menuitem, COLOR_WHITE);
+}
+
+
+void
+on_papercolorYellow_activate           (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_papercolor_activate(menuitem, COLOR_YELLOW);
+}
+
+
+void
+on_papercolorPink_activate             (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_papercolor_activate(menuitem, COLOR_RED);
+}
+
+
+void
+on_papercolorOrange_activate           (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_papercolor_activate(menuitem, COLOR_ORANGE);
+}
+
+
+void
+on_papercolorBlue_activate             (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_papercolor_activate(menuitem, COLOR_BLUE);
+}
+
+
+void
+on_papercolorGreen_activate            (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_papercolor_activate(menuitem, COLOR_GREEN);
+}
+
+
+void
+on_papercolorOther_activate            (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_paperstylePlain_activate            (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_paperstyle_activate(menuitem, RULING_NONE);
+}
+
+
+void
+on_paperstyleLined_activate            (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_paperstyle_activate(menuitem, RULING_LINED);
+}
+
+
+void
+on_paperstyleRuled_activate            (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_paperstyle_activate(menuitem, RULING_RULED);
+}
+
+
+void
+on_paperstyleGraph_activate            (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_paperstyle_activate(menuitem, RULING_GRAPH);
+}
+
+
+void
+on_journalLoadBackground_activate      (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  GtkWidget *dialog, *attach_opt;
+  struct Background *bg;
+  struct Page *pg;
+  int pageno;
+  GList *bglist, *bglistiter;
+  GtkFileFilter *filt_all, *filt_pix, *filt_pspdf;
+  char *filename;
+  gboolean attach;
+  
+  dialog = gtk_file_chooser_dialog_new("Open Background", GTK_WINDOW (winMain),
+     GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+     GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
+     
+  filt_all = gtk_file_filter_new();
+  gtk_file_filter_set_name(filt_all, "All files");
+  gtk_file_filter_add_pattern(filt_all, "*");
+  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
+
+#if GTK_CHECK_VERSION(2,6,0)
+
+  if (!gtk_check_version(2, 6, 0)) {
+    filt_pix = gtk_file_filter_new();
+    gtk_file_filter_set_name(filt_pix, "Bitmap files");
+    gtk_file_filter_add_pixbuf_formats(filt_pix);
+    gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pix);
+  }
+  
+#endif
+
+  filt_pspdf = gtk_file_filter_new();
+  gtk_file_filter_set_name(filt_pspdf, "PS/PDF files (as bitmaps)");
+  gtk_file_filter_add_pattern(filt_pspdf, "*.ps");
+  gtk_file_filter_add_pattern(filt_pspdf, "*.pdf");
+  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pspdf);
+
+  attach_opt = gtk_check_button_new_with_label("Attach file to the journal");
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(attach_opt), FALSE);
+  gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER (dialog), attach_opt);
+  
+  if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
+    gtk_widget_destroy(dialog);
+    return;
+  }
+  filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+  attach = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(attach_opt));
+  gtk_widget_destroy(dialog);
+  
+  set_cursor_busy(TRUE);
+  bg = attempt_load_pix_bg(filename, attach);
+  if (bg != NULL) bglist = g_list_append(NULL, bg);
+  else bglist = attempt_load_gv_bg(filename);
+  set_cursor_busy(FALSE);
+  
+  if (bglist == NULL) {
+    dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL,
+      GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+      "Error opening background '%s'", filename);
+    gtk_dialog_run(GTK_DIALOG(dialog));
+    gtk_widget_destroy(dialog);
+    g_free(filename);
+    return;
+  }
+
+  g_free(filename);
+  reset_selection();
+  pageno = ui.pageno;
+
+  for (bglistiter = bglist, pageno = ui.pageno; 
+           bglistiter!=NULL; bglistiter = bglistiter->next, pageno++) {
+    prepare_new_undo();
+    if (bglistiter->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
+    if (bglistiter->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
+
+    bg = (struct Background *)bglistiter->data;
+    
+    if (pageno == journal.npages) {
+      undo->type = ITEM_NEW_PAGE;
+      pg = new_page_with_bg(bg, 
+              gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale,
+              gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale);
+      journal.pages = g_list_append(journal.pages, pg);
+      journal.npages++;
+      undo->val = pageno;
+      undo->page = pg;
+    } else
+    {
+      pg = g_list_nth_data(journal.pages, pageno);
+      undo->type = ITEM_NEW_BG_RESIZE;
+      undo->page = pg;
+      undo->bg = pg->bg;
+      bg->canvas_item = undo->bg->canvas_item;
+      undo->bg->canvas_item = NULL;
+      undo->val_x = pg->width;
+      undo->val_y = pg->height;
+      pg->bg = bg;
+      pg->width = gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale;
+      pg->height = gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale;
+      make_page_clipbox(pg);
+      update_canvas_bg(pg);
+    }
+  }
+
+  g_list_free(bglist);
+  if (ui.zoom != DEFAULT_ZOOM) {
+    ui.zoom = DEFAULT_ZOOM;
+    gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+    rescale_bg_pixmaps();
+  }
+  do_switch_page(ui.pageno, TRUE);
+}
+
+void
+on_journalScreenshot_activate          (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  struct Background *bg;
+  
+  reset_selection();
+  gtk_window_iconify(GTK_WINDOW(winMain)); // hide ourselves
+  gdk_display_sync(gdk_display_get_default());
+
+  if (ui.cursor!=NULL)
+    gdk_cursor_unref(ui.cursor);
+  ui.cursor = gdk_cursor_new(GDK_TCROSS);
+
+  bg = attempt_screenshot_bg();
+    
+  gtk_window_deiconify(GTK_WINDOW(winMain));
+  update_cursor();
+  if (bg==NULL) return;
+
+  prepare_new_undo();
+  undo->type = ITEM_NEW_BG_RESIZE;
+  undo->page = ui.cur_page;
+  undo->bg = ui.cur_page->bg;
+  bg->canvas_item = undo->bg->canvas_item;
+  undo->bg->canvas_item = NULL;
+  undo->val_x = ui.cur_page->width;
+  undo->val_y = ui.cur_page->height;
+
+  ui.cur_page->bg = bg;
+  ui.cur_page->width = gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale;
+  ui.cur_page->height = gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale;
+
+  make_page_clipbox(ui.cur_page);
+  update_canvas_bg(ui.cur_page);
+
+  if (ui.zoom != DEFAULT_ZOOM) {
+    ui.zoom = DEFAULT_ZOOM;
+    gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+    rescale_bg_pixmaps();
+  }
+  do_switch_page(ui.pageno, TRUE);
+}
+
+
+void
+on_journalApplyAllPages_activate       (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_toolsPen_activate                   (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
+    if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
+      return;
+  } else {
+    if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
+      return;
+  }
+  
+  if (ui.toolno == TOOL_PEN) return;
+  
+  reset_selection();
+  ui.toolno = TOOL_PEN;
+  ui.ruler = FALSE;
+  ui.cur_brush = ui.brushes+TOOL_PEN;
+  update_tool_buttons();
+  update_tool_menu();
+  update_color_menu();
+  update_cursor();
+}
+
+
+void
+on_toolsEraser_activate                (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
+    if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
+      return;
+  } else {
+    if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
+      return;
+  }
+  
+  if (ui.toolno == TOOL_ERASER) return;
+  
+  reset_selection();
+  ui.toolno = TOOL_ERASER;
+  ui.ruler = FALSE;
+  ui.cur_brush = ui.brushes+TOOL_ERASER;
+  update_tool_buttons();
+  update_tool_menu();
+  update_color_menu();
+  update_cursor();
+}
+
+
+void
+on_toolsHighlighter_activate           (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
+    if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
+      return;
+  } else {
+    if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
+      return;
+  }
+  
+  if (ui.toolno == TOOL_HIGHLIGHTER) return;
+  
+  reset_selection();
+  ui.toolno = TOOL_HIGHLIGHTER;
+  ui.ruler = FALSE;
+  ui.cur_brush = ui.brushes+TOOL_HIGHLIGHTER;
+  update_tool_buttons();
+  update_tool_menu();
+  update_color_menu();
+  update_cursor();
+}
+
+
+void
+on_toolsText_activate                  (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_toolsSelectRegion_activate          (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_toolsSelectRectangle_activate       (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
+    if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
+      return;
+  } else {
+    if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
+      return;
+  }
+  
+  if (ui.toolno == TOOL_SELECTRECT) return;
+  
+  ui.toolno = TOOL_SELECTRECT;
+  ui.ruler = FALSE;
+  update_tool_buttons();
+  update_tool_menu();
+  update_color_menu();
+  update_cursor();
+}
+
+
+void
+on_toolsVerticalSpace_activate         (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
+    if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
+      return;
+  } else {
+    if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
+      return;
+  }
+  
+  if (ui.toolno == TOOL_VERTSPACE) return;
+  
+  reset_selection();
+  ui.toolno = TOOL_VERTSPACE;
+  ui.ruler = FALSE;
+  update_tool_buttons();
+  update_tool_menu();
+  update_color_menu();
+  update_cursor();
+}
+
+
+void
+on_colorBlack_activate                 (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_color_activate(menuitem, COLOR_BLACK);
+}
+
+
+void
+on_colorBlue_activate                  (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_color_activate(menuitem, COLOR_BLUE);
+
+}
+
+
+void
+on_colorRed_activate                   (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_color_activate(menuitem, COLOR_RED);
+}
+
+
+void
+on_colorGreen_activate                 (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_color_activate(menuitem, COLOR_GREEN);
+}
+
+
+void
+on_colorGray_activate                  (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_color_activate(menuitem, COLOR_GRAY);
+}
+
+
+void
+on_colorLightBlue_activate             (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_color_activate(menuitem, COLOR_LIGHTBLUE);
+}
+
+
+void
+on_colorLightGreen_activate            (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_color_activate(menuitem, COLOR_LIGHTGREEN);
+}
+
+
+void
+on_colorMagenta_activate               (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_color_activate(menuitem, COLOR_MAGENTA);
+}
+
+
+void
+on_colorOrange_activate                (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_color_activate(menuitem, COLOR_ORANGE);
+}
+
+
+void
+on_colorYellow_activate                (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_color_activate(menuitem, COLOR_YELLOW);
+}
+
+
+void
+on_colorWhite_activate                 (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_color_activate(menuitem, COLOR_WHITE);
+}
+
+
+void
+on_colorOther_activate                 (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_penthicknessVeryFine_activate       (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_VERYFINE);
+}
+
+
+void
+on_penthicknessFine_activate           (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_FINE);
+}
+
+
+void
+on_penthicknessMedium_activate         (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_MEDIUM);
+}
+
+
+void
+on_penthicknessThick_activate          (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_THICK);
+}
+
+
+void
+on_penthicknessVeryThick_activate      (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_VERYTHICK);
+}
+
+
+void
+on_eraserFine_activate                 (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_FINE);
+}
+
+
+void
+on_eraserMedium_activate               (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_MEDIUM);
+}
+
+
+void
+on_eraserThick_activate                (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_THICK);
+}
+
+
+void
+on_eraserStandard_activate             (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
+  ui.brushes[TOOL_ERASER].tool_options = TOOLOPT_ERASER_STANDARD;
+}
+
+
+void
+on_eraserWhiteout_activate             (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
+  ui.brushes[TOOL_ERASER].tool_options = TOOLOPT_ERASER_WHITEOUT;
+}
+
+
+void
+on_eraserDeleteStrokes_activate        (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
+  ui.brushes[TOOL_ERASER].tool_options = TOOLOPT_ERASER_STROKES;
+}
+
+
+void
+on_highlighterFine_activate            (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_FINE);
+}
+
+
+void
+on_highlighterMedium_activate          (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_MEDIUM);
+}
+
+
+void
+on_highlighterThick_activate           (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_THICK);
+}
+
+
+void
+on_toolsTextFont_activate              (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_toolsDefaultPen_activate            (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  reset_selection();
+  g_memmove(ui.brushes+TOOL_PEN, ui.default_brushes+TOOL_PEN, sizeof(struct Brush));
+  ui.toolno = TOOL_PEN;
+  ui.cur_brush = ui.brushes+TOOL_PEN;
+  update_tool_buttons();
+  update_tool_menu();
+  update_pen_props_menu();
+  update_color_menu();
+  update_cursor();
+}
+
+
+void
+on_toolsDefaultEraser_activate         (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  reset_selection();
+  g_memmove(ui.brushes+TOOL_ERASER, ui.default_brushes+TOOL_ERASER, sizeof(struct Brush));
+  ui.toolno = TOOL_ERASER;
+  ui.cur_brush = ui.brushes+TOOL_ERASER;
+  update_tool_buttons();
+  update_tool_menu();
+  update_eraser_props_menu();
+  update_color_menu();
+  update_cursor();
+}
+
+
+void
+on_toolsDefaultHighlighter_activate    (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  reset_selection();
+  g_memmove(ui.brushes+TOOL_HIGHLIGHTER, ui.default_brushes+TOOL_HIGHLIGHTER, sizeof(struct Brush));
+  ui.toolno = TOOL_HIGHLIGHTER;
+  ui.cur_brush = ui.brushes+TOOL_HIGHLIGHTER;
+  update_tool_buttons();
+  update_tool_menu();
+  update_highlighter_props_menu();
+  update_color_menu();
+  update_cursor();
+}
+
+void
+on_toolsDefaultText_activate           (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_toolsSetAsDefault_activate          (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (ui.toolno < NUM_STROKE_TOOLS)
+    g_memmove(ui.default_brushes+ui.toolno, ui.brushes+ui.toolno, sizeof(struct Brush));
+}
+
+
+void
+on_toolsRuler_activate                 (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  gboolean active;
+  
+  if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
+    active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
+  else
+    active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
+
+  if (active == ui.ruler) return;
+  
+  if (active && (ui.toolno!=TOOL_PEN && ui.toolno!=TOOL_HIGHLIGHTER)) {
+    reset_selection();
+    ui.toolno = TOOL_PEN;
+    ui.cur_brush = ui.brushes+TOOL_PEN;
+    update_color_menu();
+    update_tool_buttons();
+    update_tool_menu();
+    update_cursor();
+  }
+  
+  ui.ruler = active;
+  update_ruler_indicator();
+}
+
+
+void
+on_optionsSavePreferences_activate     (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_helpIndex_activate                  (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+
+}
+
+
+void
+on_helpAbout_activate                  (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  GtkWidget *aboutDialog;
+  GtkLabel *labelTitle;
+  
+  aboutDialog = create_aboutDialog ();
+  labelTitle = GTK_LABEL(g_object_get_data(G_OBJECT(aboutDialog), "labelTitle"));
+  gtk_label_set_markup(labelTitle, 
+    "<span size=\"xx-large\" weight=\"bold\">Xournal " VERSION "</span>");
+  gtk_dialog_run (GTK_DIALOG(aboutDialog));
+  gtk_widget_destroy(aboutDialog);
+}
+
+
+void
+on_buttonToolDefault_clicked           (GtkToolButton   *toolbutton,
+                                        gpointer         user_data)
+{
+  if (ui.toolno < NUM_STROKE_TOOLS) {
+    g_memmove(ui.brushes+ui.toolno, ui.default_brushes+ui.toolno, sizeof(struct Brush));
+    update_thickness_buttons();
+    update_color_buttons();
+    update_color_menu();
+    if (ui.toolno == TOOL_PEN) update_pen_props_menu();
+    if (ui.toolno == TOOL_ERASER) update_eraser_props_menu();
+    if (ui.toolno == TOOL_HIGHLIGHTER) update_highlighter_props_menu();
+    update_cursor();
+  }
+}
+
+
+void
+on_buttonFine_clicked                  (GtkToolButton   *toolbutton,
+                                        gpointer         user_data)
+{
+  process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno, THICKNESS_FINE);
+}
+
+
+void
+on_buttonMedium_clicked                (GtkToolButton   *toolbutton,
+                                        gpointer         user_data)
+{
+  process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno, THICKNESS_MEDIUM);
+}
+
+
+void
+on_buttonThick_clicked                 (GtkToolButton   *toolbutton,
+                                        gpointer         user_data)
+{
+  process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno, THICKNESS_THICK);
+}
+
+
+gboolean
+on_canvas_button_press_event           (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data)
+{
+  double pt[2];
+  gboolean page_change;
+  struct Page *tmppage;
+  GtkWidget *dialog;
+  
+  if (ui.cur_item_type != ITEM_NONE) return FALSE; // we're already doing something
+  if (event->button > 3) return FALSE; // no painting with the mouse wheel!
+
+  if (ui.use_xinput) { 
+    if (event->device->source == GDK_SOURCE_MOUSE) return FALSE;
+    // re-get the axis values since Synaptics sends bogus ones
+    gdk_device_get_state(event->device, event->window, event->axes, NULL);
+    fix_xinput_coords((GdkEvent *)event);
+  }
+  else if (event->device->source != GDK_SOURCE_MOUSE) return FALSE;
+
+  if ((ui.use_xinput && event->device->source == GDK_SOURCE_ERASER) ||
+      (ui.emulate_eraser && event->button >= 2)) {
+    ui.saved_toolno = ui.toolno;
+    ui.saved_ruler = ui.ruler;
+    reset_selection();
+    ui.toolno = TOOL_ERASER;
+    ui.ruler = FALSE;
+    ui.cur_brush = ui.brushes + TOOL_ERASER;
+    update_tool_buttons();
+    update_tool_menu();
+    update_color_menu();
+    update_cursor();
+  }
+
+  // check whether we're in a page
+  page_change = FALSE;
+  tmppage = ui.cur_page;
+  get_pointer_coords((GdkEvent *)event, pt);
+  while (ui.view_continuous && (pt[1] < - VIEW_CONTINUOUS_SKIP)) {
+    if (ui.pageno == 0) break;
+    page_change = TRUE;
+    ui.pageno--;
+    tmppage = g_list_nth_data(journal.pages, ui.pageno);
+    pt[1] += tmppage->height + VIEW_CONTINUOUS_SKIP;
+  }
+  while (ui.view_continuous && (pt[1] > tmppage->height + VIEW_CONTINUOUS_SKIP)) {
+    if (ui.pageno == journal.npages-1) break;
+    pt[1] -= tmppage->height + VIEW_CONTINUOUS_SKIP;
+    page_change = TRUE;
+    ui.pageno++;
+    tmppage = g_list_nth_data(journal.pages, ui.pageno);
+  }
+  if (page_change) do_switch_page(ui.pageno, FALSE);
+  
+  // can't paint on the background...
+
+  if (ui.cur_layer == NULL) {
+    if (ui.saved_toolno >=0) {
+      ui.toolno = ui.saved_toolno;
+      ui.ruler = ui.saved_ruler;
+      ui.saved_toolno = -1;
+      if (ui.toolno < NUM_STROKE_TOOLS) ui.cur_brush = ui.brushes + ui.toolno;
+      update_tool_buttons();
+      update_tool_menu();
+      update_color_menu();
+      update_cursor();
+    }
+    /* warn */
+    dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL,
+      GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "Drawing is not allowed on the "
+      "background layer.\n Switching to Layer 1.");
+    gtk_dialog_run(GTK_DIALOG(dialog));
+    gtk_widget_destroy(dialog);
+    on_viewShowLayer_activate(NULL, NULL);
+    return;
+  }
+  
+  // process the event
+  ui.which_mouse_button = event->button;
+  
+  if (ui.toolno == TOOL_PEN || ui.toolno == TOOL_HIGHLIGHTER ||
+     (ui.toolno == TOOL_ERASER && ui.cur_brush->tool_options == TOOLOPT_ERASER_WHITEOUT)) {
+    create_new_stroke((GdkEvent *)event);
+  } 
+  else if (ui.toolno == TOOL_ERASER) {
+    ui.cur_item_type = ITEM_ERASURE;
+    do_eraser((GdkEvent *)event, ui.cur_brush->thickness/2,
+               ui.cur_brush->tool_options == TOOLOPT_ERASER_STROKES);
+  }
+  else if (ui.toolno == TOOL_SELECTRECT) {
+    if (!start_movesel((GdkEvent *)event))
+      start_selectrect((GdkEvent *)event);
+  }
+  else if (ui.toolno == TOOL_VERTSPACE) {
+    start_vertspace((GdkEvent *)event);
+  }
+  return FALSE;
+}
+
+
+gboolean
+on_canvas_button_release_event         (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data)
+{
+  if (ui.cur_item_type == ITEM_NONE) return FALSE; // not doing anything
+
+  if (event->button != ui.which_mouse_button) return FALSE; // ignore
+
+  if (ui.use_xinput) {
+    if (event->device->source == GDK_SOURCE_MOUSE) return FALSE;
+    fix_xinput_coords((GdkEvent *)event);
+  }
+  else if (event->device->source != GDK_SOURCE_MOUSE) return FALSE;
+
+  if (ui.saved_toolno >= 0) {
+    ui.toolno = ui.saved_toolno;
+    ui.ruler = ui.saved_ruler;
+    ui.saved_toolno = -1;
+    if (ui.toolno < NUM_STROKE_TOOLS) ui.cur_brush = ui.brushes + ui.toolno;
+    update_tool_buttons();
+    update_tool_menu();
+    update_color_menu();
+    update_cursor();
+  }
+  
+  if (ui.cur_item_type == ITEM_STROKE) {
+    finalize_stroke();
+  }
+  else if (ui.cur_item_type == ITEM_ERASURE) {
+    finalize_erasure();
+  }
+  else if (ui.cur_item_type == ITEM_SELECTRECT) {
+    finalize_selectrect();
+  }
+  else if (ui.cur_item_type == ITEM_MOVESEL) {
+    finalize_movesel();
+  }
+  
+  return FALSE;
+}
+
+
+gboolean
+on_canvas_enter_notify_event           (GtkWidget       *widget,
+                                        GdkEventCrossing *event,
+                                        gpointer         user_data)
+{
+
+  return FALSE;
+}
+
+
+gboolean
+on_canvas_expose_event                 (GtkWidget       *widget,
+                                        GdkEventExpose  *event,
+                                        gpointer         user_data)
+{
+
+  return FALSE;
+}
+
+
+gboolean
+on_canvas_key_press_event              (GtkWidget       *widget,
+                                        GdkEventKey     *event,
+                                        gpointer         user_data)
+{
+
+  return FALSE;
+}
+
+
+gboolean
+on_canvas_motion_notify_event          (GtkWidget       *widget,
+                                        GdkEventMotion  *event,
+                                        gpointer         user_data)
+{
+  gboolean looks_wrong;
+  double pt[2];
+  
+  if (ui.cur_item_type == ITEM_NONE) return FALSE; // we don't care
+
+  if (ui.use_xinput) { 
+    if (event->device->source == GDK_SOURCE_MOUSE) return FALSE;
+    fix_xinput_coords((GdkEvent *)event);
+  }
+  else if (event->device->source != GDK_SOURCE_MOUSE) return FALSE;
+
+  looks_wrong = !(event->state & (1<<(7+ui.which_mouse_button)));
+  
+  if (looks_wrong) { /* mouse button shouldn't be up... give up */
+    if (ui.cur_item_type == ITEM_STROKE) {
+      finalize_stroke();
+    }
+    else if (ui.cur_item_type == ITEM_ERASURE) {
+      finalize_erasure();
+    }
+    else if (ui.cur_item_type == ITEM_SELECTRECT) {
+      finalize_selectrect();
+    }
+    else if (ui.cur_item_type == ITEM_MOVESEL) {
+      finalize_movesel();
+    }
+    return FALSE;
+  }
+  
+  if (ui.cur_item_type == ITEM_STROKE) {
+    continue_stroke((GdkEvent *)event);
+  }
+  else if (ui.cur_item_type == ITEM_ERASURE) {
+    do_eraser((GdkEvent *)event, ui.cur_brush->thickness/2,
+               ui.cur_brush->tool_options == TOOLOPT_ERASER_STROKES);
+  }
+  else if (ui.cur_item_type == ITEM_SELECTRECT) {
+    get_pointer_coords((GdkEvent *)event, pt);
+    ui.selection->bbox.right = pt[0];
+    ui.selection->bbox.bottom = pt[1];
+    gnome_canvas_item_set(ui.selection->canvas_item,
+                               "x2", pt[0], "y2", pt[1], NULL);
+  }
+  else if (ui.cur_item_type == ITEM_MOVESEL) {
+    continue_movesel((GdkEvent *)event);
+  }
+  
+  return FALSE;
+}
+
+
+void
+on_comboLayer_changed                  (GtkComboBox     *combobox,
+                                        gpointer         user_data)
+{
+  int val;
+
+  if (ui.in_update_page_stuff) return; // avoid a bad retroaction
+
+  gtk_widget_grab_focus(GTK_WIDGET(canvas)); // stop focus on us
+
+  val = gtk_combo_box_get_active(combobox);
+  if (val == -1) return;
+  val = ui.cur_page->nlayers-1-val;
+  if (val == ui.layerno) return;
+
+  reset_selection();
+  while (val>ui.layerno) {
+    ui.layerno++;
+    ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
+    gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group));
+  }
+  while (val<ui.layerno) {
+    gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group));
+    ui.layerno--;
+    if (ui.layerno<0) ui.cur_layer = NULL;
+    else ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
+  }
+  update_page_stuff();
+}
+
+
+gboolean
+on_winMain_delete_event                (GtkWidget       *widget,
+                                        GdkEvent        *event,
+                                        gpointer         user_data)
+{
+  if (ok_to_close()) gtk_main_quit();
+  return TRUE;
+}
+
+
+void
+on_optionsUseXInput_activate           (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  ui.allow_xinput = ui.use_xinput =
+    gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
+}
+
+void
+on_vscroll_changed                     (GtkAdjustment   *adjustment,
+                                        gpointer         user_data)
+{
+  gboolean need_update;
+  double viewport_top, viewport_bottom;
+  struct Page *tmppage;
+  
+  if (!ui.view_continuous) return;
+  
+  if (ui.progressive_bg) rescale_bg_pixmaps();
+  need_update = FALSE;
+  viewport_top = adjustment->value / ui.zoom;
+  viewport_bottom = (adjustment->value + adjustment->page_size) / ui.zoom;
+  tmppage = ui.cur_page;
+  while (viewport_top > tmppage->voffset + tmppage->height) {
+    if (ui.pageno == journal.npages-1) break;
+    need_update = TRUE;
+    ui.pageno++;
+    tmppage = g_list_nth_data(journal.pages, ui.pageno);
+  }
+  while (viewport_bottom < tmppage->voffset) {
+    if (ui.pageno == 0) break;
+    need_update = TRUE;
+    ui.pageno--;
+    tmppage = g_list_nth_data(journal.pages, ui.pageno);
+  }
+  if (need_update) do_switch_page(ui.pageno, FALSE);
+  return;
+}
+
+void
+on_spinPageNo_value_changed            (GtkSpinButton   *spinbutton,
+                                        gpointer         user_data)
+{
+  int val;
+
+  if (ui.in_update_page_stuff) return; // avoid a bad retroaction
+
+  gtk_widget_grab_focus(GTK_WIDGET(canvas)); // stop blink-blink text cursor
+
+  val = gtk_spin_button_get_value_as_int(spinbutton) - 1;
+
+  if (val == journal.npages) { // create a page at end
+    if (page_ops_forbidden()) return;
+    on_journalNewPageEnd_activate(NULL, NULL);
+    return;
+  }
+
+  if (val == ui.pageno) return;
+  if (val < 0) val = 0;
+  if (val > journal.npages-1) val = journal.npages-1;
+  do_switch_page(val, TRUE);
+}
+
+
+void
+on_journalDefaultBackground_activate   (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  reset_selection();
+  prepare_new_undo();
+  undo->type = ITEM_NEW_BG_RESIZE;
+  undo->page = ui.cur_page;
+  undo->bg = ui.cur_page->bg;
+  undo->val_x = ui.cur_page->width;
+  undo->val_y = ui.cur_page->height; 
+  
+  ui.cur_page->bg = (struct Background *)g_memdup(ui.default_page.bg, sizeof(struct Background));
+  ui.cur_page->width = ui.default_page.width;
+  ui.cur_page->height = ui.default_page.height;
+  ui.cur_page->bg->canvas_item = undo->bg->canvas_item;
+  undo->bg->canvas_item = NULL;
+  
+  make_page_clipbox(ui.cur_page);
+  update_canvas_bg(ui.cur_page);
+  do_switch_page(ui.pageno, TRUE);
+}
+
+
+void
+on_journalSetAsDefault_activate        (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  if (ui.cur_page->bg->type != BG_SOLID) return;
+  
+  prepare_new_undo();
+  undo->type = ITEM_NEW_DEFAULT_BG;
+  undo->val_x = ui.default_page.width;
+  undo->val_y = ui.default_page.height;
+  undo->bg = ui.default_page.bg;
+  
+  ui.default_page.width = ui.cur_page->width;
+  ui.default_page.height = ui.cur_page->height;
+  ui.default_page.bg = (struct Background *)g_memdup(ui.cur_page->bg, sizeof(struct Background));
+  ui.default_page.bg->canvas_item = NULL;
+}
+
+
+void
+on_comboStdSizes_changed               (GtkComboBox     *combobox,
+                                        gpointer         user_data)
+{
+  GtkEntry *entry;
+  GtkComboBox *comboUnit;
+  int val;
+  gchar text[20];
+
+  if (papersize_need_init) {
+    gtk_combo_box_set_active(combobox, papersize_std);
+    papersize_need_init = FALSE;
+  } else {
+    val = gtk_combo_box_get_active(combobox);
+    if (val == -1 || val == papersize_std) return;
+    papersize_std = val;
+    if (val == STD_SIZE_CUSTOM) return;
+    papersize_unit = std_units[val];
+    papersize_width = std_widths[val];
+    papersize_height = std_heights[val];
+  }
+  comboUnit = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboUnit"));
+  gtk_combo_box_set_active(comboUnit, papersize_unit);
+  entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryWidth"));
+  g_snprintf(text, 20, "%.2f", papersize_width/unit_sizes[papersize_unit]);
+  if (g_str_has_suffix(text, ".00")) 
+    g_snprintf(text, 20, "%d", (int) (papersize_width/unit_sizes[papersize_unit]));
+  gtk_entry_set_text(entry, text);
+  entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryHeight"));
+  g_snprintf(text, 20, "%.2f", papersize_height/unit_sizes[papersize_unit]);
+  if (g_str_has_suffix(text, ".00")) 
+    g_snprintf(text, 20, "%d", (int) (papersize_height/unit_sizes[papersize_unit]));
+  gtk_entry_set_text(entry, text);
+}
+
+
+void
+on_entryWidth_changed                  (GtkEditable     *editable,
+                                        gpointer         user_data)
+{
+  double val;
+  const gchar *text;
+  gchar *ptr;
+  GtkComboBox *comboStdSizes;
+  
+  text = gtk_entry_get_text(GTK_ENTRY(editable));
+  val = strtod(text, &ptr);
+  papersize_width_valid = (*ptr == 0 && val > 0.);
+  if (!papersize_width_valid) return; // invalid entry
+  val *= unit_sizes[papersize_unit];
+  if (fabs(val - papersize_width) < 0.1) return; // no change
+  papersize_std = STD_SIZE_CUSTOM;
+  papersize_width = val;
+  comboStdSizes = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboStdSizes"));
+  gtk_combo_box_set_active(comboStdSizes, papersize_std);
+}
+
+
+void
+on_entryHeight_changed                 (GtkEditable     *editable,
+                                        gpointer         user_data)
+{
+  double val;
+  const gchar *text;
+  gchar *ptr;
+  GtkComboBox *comboStdSizes;
+  
+  text = gtk_entry_get_text(GTK_ENTRY(editable));
+  val = strtod(text, &ptr);
+  papersize_height_valid = (*ptr == 0 && val > 0.);
+  if (!papersize_height_valid) return; // invalid entry
+  val *= unit_sizes[papersize_unit];
+  if (fabs(val - papersize_height) < 0.1) return; // no change
+  papersize_std = STD_SIZE_CUSTOM;
+  papersize_height = val;
+  comboStdSizes = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboStdSizes"));
+  gtk_combo_box_set_active(comboStdSizes, papersize_std);
+}
+
+
+void
+on_comboUnit_changed                   (GtkComboBox     *combobox,
+                                        gpointer         user_data)
+{
+  GtkEntry *entry;
+  int val;
+  gchar text[20];
+
+  val = gtk_combo_box_get_active(combobox);
+  if (val == -1 || val == papersize_unit) return;
+  papersize_unit = val;
+  entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryWidth"));
+  if (papersize_width_valid) {
+    g_snprintf(text, 20, "%.2f", papersize_width/unit_sizes[papersize_unit]);
+    if (g_str_has_suffix(text, ".00")) 
+      g_snprintf(text, 20, "%d", (int) (papersize_width/unit_sizes[papersize_unit]));
+  } else *text = 0;
+  gtk_entry_set_text(entry, text);
+  if (papersize_height_valid) {
+    entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryHeight"));
+    g_snprintf(text, 20, "%.2f", papersize_height/unit_sizes[papersize_unit]);
+    if (g_str_has_suffix(text, ".00")) 
+      g_snprintf(text, 20, "%d", (int) (papersize_height/unit_sizes[papersize_unit]));
+  } else *text = 0;
+  gtk_entry_set_text(entry, text);
+}
+
+
+void
+on_viewFullscreen_activate             (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  gboolean active;
+  
+  if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
+    active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
+  else
+    active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
+
+  if (active == ui.fullscreen) return;
+  ui.fullscreen = active;
+
+  if (ui.fullscreen) {
+    gtk_window_fullscreen(GTK_WINDOW(winMain));
+    gtk_widget_hide(GET_COMPONENT("menubar"));
+    gtk_widget_hide(GET_COMPONENT("hbox1"));
+  } 
+  else {
+    gtk_window_unfullscreen(GTK_WINDOW(winMain));
+    gtk_widget_show(GET_COMPONENT("menubar"));
+    gtk_widget_show(GET_COMPONENT("hbox1"));
+  }
+}
+
+
+void
+on_optionsEmulateEraser_activate       (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  ui.emulate_eraser =
+    gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
+}
+
+
+void
+on_optionsAntialiasBG_activate         (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  gboolean active;
+  
+  active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
+  if (ui.antialias_bg == active) return;
+  ui.antialias_bg = active;
+  rescale_bg_pixmaps();
+} 
+
+
+void
+on_optionsProgressiveBG_activate       (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+  gboolean active;
+  
+  active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
+  if (ui.progressive_bg == active) return;
+  ui.progressive_bg = active;
+  if (!ui.progressive_bg) rescale_bg_pixmaps();
+}
+