--- /dev/null
+#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();
+}
+