2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) any later version.
7 * This software is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include <libgnomecanvas/libgnomecanvas.h>
26 #include <glib/gstdio.h>
27 #include <gdk/gdkkeysyms.h>
30 #include "xo-callbacks.h"
31 #include "xo-interface.h"
32 #include "xo-support.h"
37 #include "xo-shapes.h"
40 on_fileNew_activate (GtkMenuItem *menuitem,
44 if (close_journal()) {
46 ui.zoom = ui.startup_zoom;
48 gtk_adjustment_set_value(gtk_layout_get_vadjustment(GTK_LAYOUT(canvas)), 0);
49 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
55 on_fileNewBackground_activate (GtkMenuItem *menuitem,
58 GtkWidget *dialog, *attach_opt;
59 GtkFileFilter *filt_all, *filt_pdf;
65 if (!ok_to_close()) return; // user aborted on save confirmation
67 dialog = gtk_file_chooser_dialog_new(_("Open PDF"), GTK_WINDOW (winMain),
68 GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
69 GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
70 #ifdef FILE_DIALOG_SIZE_BUGFIX
71 gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
74 filt_all = gtk_file_filter_new();
75 gtk_file_filter_set_name(filt_all, _("All files"));
76 gtk_file_filter_add_pattern(filt_all, "*");
77 filt_pdf = gtk_file_filter_new();
78 gtk_file_filter_set_name(filt_pdf, _("PDF files"));
79 gtk_file_filter_add_pattern(filt_pdf, "*.pdf");
80 gtk_file_filter_add_pattern(filt_pdf, "*.PDF");
81 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pdf);
82 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
84 if (ui.default_path!=NULL) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
86 attach_opt = gtk_check_button_new_with_label(_("Attach file to the journal"));
87 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(attach_opt), FALSE);
88 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER (dialog), attach_opt);
90 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
91 gtk_widget_destroy(dialog);
94 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
95 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(attach_opt)))
96 file_domain = DOMAIN_ATTACH;
97 else file_domain = DOMAIN_ABSOLUTE;
99 gtk_widget_destroy(dialog);
101 set_cursor_busy(TRUE);
102 ui.saved = TRUE; // force close_journal to work
104 while (bgpdf.status != STATUS_NOT_INIT) {
105 // waiting for pdf processes to finish dying
106 gtk_main_iteration();
109 ui.zoom = ui.startup_zoom;
110 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
112 success = init_bgpdf(filename, TRUE, file_domain);
113 set_cursor_busy(FALSE);
120 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
121 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening file '%s'"), filename);
122 gtk_dialog_run(GTK_DIALOG(dialog));
123 gtk_widget_destroy(dialog);
129 on_fileOpen_activate (GtkMenuItem *menuitem,
133 GtkFileFilter *filt_all, *filt_xoj;
138 if (!ok_to_close()) return; // user aborted on save confirmation
140 dialog = gtk_file_chooser_dialog_new(_("Open Journal"), GTK_WINDOW (winMain),
141 GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
142 GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
143 #ifdef FILE_DIALOG_SIZE_BUGFIX
144 gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
147 filt_all = gtk_file_filter_new();
148 gtk_file_filter_set_name(filt_all, _("All files"));
149 gtk_file_filter_add_pattern(filt_all, "*");
150 filt_xoj = gtk_file_filter_new();
151 gtk_file_filter_set_name(filt_xoj, _("Xournal files"));
152 gtk_file_filter_add_pattern(filt_xoj, "*.xoj");
153 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_xoj);
154 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
156 if (ui.default_path!=NULL) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
158 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
159 gtk_widget_destroy(dialog);
162 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
163 gtk_widget_destroy(dialog);
165 set_cursor_busy(TRUE);
166 success = open_journal(filename);
167 set_cursor_busy(FALSE);
168 if (success) { g_free(filename); return; }
171 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
172 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening file '%s'"), filename);
173 gtk_dialog_run(GTK_DIALOG(dialog));
174 gtk_widget_destroy(dialog);
181 on_fileSave_activate (GtkMenuItem *menuitem,
187 if (ui.filename == NULL) {
188 on_fileSaveAs_activate(menuitem, user_data);
191 set_cursor_busy(TRUE);
192 if (save_journal(ui.filename)) { // success
193 set_cursor_busy(FALSE);
197 set_cursor_busy(FALSE);
199 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
200 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error saving file '%s'"), ui.filename);
201 gtk_dialog_run(GTK_DIALOG(dialog));
202 gtk_widget_destroy(dialog);
207 on_fileSaveAs_activate (GtkMenuItem *menuitem,
210 GtkWidget *dialog, *warning_dialog;
211 GtkFileFilter *filt_all, *filt_xoj;
216 struct stat stat_buf;
219 dialog = gtk_file_chooser_dialog_new(_("Save Journal"), GTK_WINDOW (winMain),
220 GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
221 GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
222 #ifdef FILE_DIALOG_SIZE_BUGFIX
223 gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
226 if (ui.filename!=NULL) {
227 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), ui.filename);
228 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), g_basename(ui.filename));
231 if (bgpdf.status!=STATUS_NOT_INIT && bgpdf.file_domain == DOMAIN_ABSOLUTE
232 && bgpdf.filename != NULL) {
233 filename = g_strdup_printf("%s.xoj", bgpdf.filename->s);
234 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), filename);
235 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), g_basename(filename));
239 curtime = time(NULL);
240 strftime(stime, 30, "%Y-%m-%d-Note-%H-%M.xoj", localtime(&curtime));
241 if (ui.default_path!=NULL)
242 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
243 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), stime);
246 filt_all = gtk_file_filter_new();
247 gtk_file_filter_set_name(filt_all, _("All files"));
248 gtk_file_filter_add_pattern(filt_all, "*");
249 filt_xoj = gtk_file_filter_new();
250 gtk_file_filter_set_name(filt_xoj, _("Xournal files"));
251 gtk_file_filter_add_pattern(filt_xoj, "*.xoj");
252 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_xoj);
253 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
255 // somehow this doesn't seem to be set by default
256 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
259 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
260 gtk_widget_destroy(dialog);
263 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
264 warn = g_file_test (filename, G_FILE_TEST_EXISTS);
265 if (warn) { // ok to overwrite an empty file
266 if (!g_stat(filename, &stat_buf))
267 if (stat_buf.st_size == 0) warn=FALSE;
269 if (warn && ui.filename!=NULL) { // ok to overwrite oneself
270 if (ui.filename[0]=='/' && !strcmp(ui.filename, filename)) warn=FALSE;
271 if (ui.filename[0]!='/' && g_str_has_suffix(filename, ui.filename)) warn=FALSE;
274 warning_dialog = gtk_message_dialog_new(GTK_WINDOW(winMain),
275 GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
276 _("Should the file %s be overwritten?"), filename);
277 if (gtk_dialog_run(GTK_DIALOG(warning_dialog)) == GTK_RESPONSE_YES)
279 gtk_widget_destroy(warning_dialog);
283 gtk_widget_destroy(dialog);
285 set_cursor_busy(TRUE);
286 if (save_journal(filename)) { // success
288 set_cursor_busy(FALSE);
289 update_file_name(filename);
292 set_cursor_busy(FALSE);
294 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
295 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error saving file '%s'"), filename);
296 gtk_dialog_run(GTK_DIALOG(dialog));
297 gtk_widget_destroy(dialog);
303 on_filePrintOptions_activate (GtkMenuItem *menuitem,
310 on_filePrint_activate (GtkMenuItem *menuitem,
313 #if GTK_CHECK_VERSION(2, 10, 0)
314 GtkPrintOperation *print;
315 GtkPrintOperationResult res;
317 int fromPage, toPage;
322 if (!gtk_check_version(2, 10, 0)) {
323 print = gtk_print_operation_new();
325 if (!ui.print_settings)
326 ui.print_settings = gtk_print_settings_new();
327 if (ui.filename!=NULL) {
328 if (g_str_has_suffix(ui.filename, ".xoj")) {
329 in_fn = g_strdup(ui.filename);
330 g_strlcpy(g_strrstr(in_fn, "xoj"), "pdf", 4);
332 else in_fn = g_strdup_printf("%s.pdf", ui.filename);
333 gtk_print_settings_set(ui.print_settings, GTK_PRINT_SETTINGS_OUTPUT_URI,
334 g_filename_to_uri(in_fn, NULL, NULL));
338 if (ui.print_settings!=NULL)
339 gtk_print_operation_set_print_settings (print, ui.print_settings);
340 gtk_print_operation_set_n_pages(print, journal.npages);
341 gtk_print_operation_set_current_page(print, ui.pageno);
342 gtk_print_operation_set_show_progress(print, TRUE);
343 if (ui.filename!=NULL) {
344 p = g_utf8_strrchr(ui.filename, -1, '/');
345 if (p==NULL) p = ui.filename;
347 gtk_print_operation_set_job_name(print, p);
349 g_signal_connect (print, "draw_page", G_CALLBACK (print_job_render_page), NULL);
350 res = gtk_print_operation_run(print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
351 GTK_WINDOW(winMain), NULL);
352 if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
353 if (ui.print_settings!=NULL) g_object_unref(ui.print_settings);
354 ui.print_settings = g_object_ref(gtk_print_operation_get_print_settings(print));
356 g_object_unref(print);
363 on_filePrintPDF_activate (GtkMenuItem *menuitem,
367 GtkWidget *dialog, *warning_dialog;
368 GtkFileFilter *filt_all, *filt_pdf;
369 char *filename, *in_fn;
375 dialog = gtk_file_chooser_dialog_new(_("Export to PDF"), GTK_WINDOW (winMain),
376 GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
377 GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
378 #ifdef FILE_DIALOG_SIZE_BUGFIX
379 gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
382 if (ui.filename!=NULL) {
383 if (g_str_has_suffix(ui.filename, ".xoj")) {
384 in_fn = g_strdup(ui.filename);
385 g_strlcpy(g_strrstr(in_fn, "xoj"), "pdf", 4);
388 in_fn = g_strdup_printf("%s.pdf", ui.filename);
389 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), in_fn);
390 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), g_basename(in_fn));
392 curtime = time(NULL);
393 strftime(stime, 30, "%Y-%m-%d-Note-%H-%M.pdf", localtime(&curtime));
394 if (ui.default_path!=NULL)
395 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
396 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), stime);
400 filt_all = gtk_file_filter_new();
401 gtk_file_filter_set_name(filt_all, _("All files"));
402 gtk_file_filter_add_pattern(filt_all, "*");
403 filt_pdf = gtk_file_filter_new();
404 gtk_file_filter_set_name(filt_pdf, _("PDF files"));
405 gtk_file_filter_add_pattern(filt_pdf, "*.pdf");
406 gtk_file_filter_add_pattern(filt_pdf, "*.PDF");
407 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pdf);
408 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
409 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
413 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
414 gtk_widget_destroy(dialog);
417 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
418 warn = g_file_test(filename, G_FILE_TEST_EXISTS);
420 warning_dialog = gtk_message_dialog_new(GTK_WINDOW(winMain),
421 GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
422 _("Should the file %s be overwritten?"), filename);
423 if (gtk_dialog_run(GTK_DIALOG(warning_dialog)) == GTK_RESPONSE_YES)
425 gtk_widget_destroy(warning_dialog);
429 gtk_widget_destroy(dialog);
431 set_cursor_busy(TRUE);
432 if (!print_to_pdf(filename)) {
433 set_cursor_busy(FALSE);
434 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
435 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error creating file '%s'"), filename);
436 gtk_dialog_run(GTK_DIALOG(dialog));
437 gtk_widget_destroy(dialog);
439 set_cursor_busy(FALSE);
445 on_fileQuit_activate (GtkMenuItem *menuitem,
449 if (ok_to_close()) gtk_main_quit ();
454 on_editUndo_activate (GtkMenuItem *menuitem,
458 GList *list, *itemlist;
459 struct UndoErasureData *erasure;
461 struct Brush tmp_brush;
462 struct Background *tmp_bg;
465 GnomeCanvasGroup *group;
468 if (undo == NULL) return; // nothing to undo!
469 reset_selection(); // safer
470 reset_recognizer(); // safer
471 if (undo->type == ITEM_STROKE || undo->type == ITEM_TEXT) {
472 // we're keeping the stroke info, but deleting the canvas item
473 gtk_object_destroy(GTK_OBJECT(undo->item->canvas_item));
474 undo->item->canvas_item = NULL;
475 // we also remove the object from its layer!
476 undo->layer->items = g_list_remove(undo->layer->items, undo->item);
477 undo->layer->nitems--;
479 else if (undo->type == ITEM_ERASURE || undo->type == ITEM_RECOGNIZER) {
480 for (list = undo->erasurelist; list!=NULL; list = list->next) {
481 erasure = (struct UndoErasureData *)list->data;
482 // delete all the created items
483 for (itemlist = erasure->replacement_items; itemlist!=NULL; itemlist = itemlist->next) {
484 it = (struct Item *)itemlist->data;
485 gtk_object_destroy(GTK_OBJECT(it->canvas_item));
486 it->canvas_item = NULL;
487 undo->layer->items = g_list_remove(undo->layer->items, it);
488 undo->layer->nitems--;
490 // recreate the deleted one
491 make_canvas_item_one(undo->layer->group, erasure->item);
493 undo->layer->items = g_list_insert(undo->layer->items, erasure->item,
495 if (erasure->npos == 0)
496 lower_canvas_item_to(undo->layer->group, erasure->item->canvas_item, NULL);
498 lower_canvas_item_to(undo->layer->group, erasure->item->canvas_item,
499 ((struct Item *)g_list_nth_data(undo->layer->items, erasure->npos-1))->canvas_item);
500 undo->layer->nitems++;
503 else if (undo->type == ITEM_NEW_BG_ONE || undo->type == ITEM_NEW_BG_RESIZE
504 || undo->type == ITEM_PAPER_RESIZE) {
505 if (undo->type != ITEM_PAPER_RESIZE) {
507 tmp_bg = undo->page->bg;
508 undo->page->bg = undo->bg;
510 undo->page->bg->canvas_item = undo->bg->canvas_item;
511 undo->bg->canvas_item = NULL;
513 if (undo->type != ITEM_NEW_BG_ONE) {
514 tmp_x = undo->page->width;
515 tmp_y = undo->page->height;
516 undo->page->width = undo->val_x;
517 undo->page->height = undo->val_y;
520 make_page_clipbox(undo->page);
522 update_canvas_bg(undo->page);
523 do_switch_page(g_list_index(journal.pages, undo->page), TRUE, TRUE);
525 else if (undo->type == ITEM_NEW_DEFAULT_BG) {
526 tmp_bg = ui.default_page.bg;
527 ui.default_page.bg = undo->bg;
529 tmp_x = ui.default_page.width;
530 tmp_y = ui.default_page.height;
531 ui.default_page.width = undo->val_x;
532 ui.default_page.height = undo->val_y;
536 else if (undo->type == ITEM_NEW_PAGE) {
537 // unmap the page; keep the page & its empty layer in memory
538 if (undo->page->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->page->group));
539 // also destroys the background and layer's canvas items
540 undo->page->group = NULL;
541 undo->page->bg->canvas_item = NULL;
542 journal.pages = g_list_remove(journal.pages, undo->page);
544 if (ui.cur_page == undo->page) ui.cur_page = NULL;
545 // so do_switch_page() won't try to remap the layers of the defunct page
546 if (ui.pageno >= undo->val) ui.pageno--;
547 if (ui.pageno < 0) ui.pageno = 0;
548 do_switch_page(ui.pageno, TRUE, TRUE);
550 else if (undo->type == ITEM_DELETE_PAGE) {
551 journal.pages = g_list_insert(journal.pages, undo->page, undo->val);
553 make_canvas_items(); // re-create the canvas items
554 do_switch_page(undo->val, TRUE, TRUE);
556 else if (undo->type == ITEM_MOVESEL) {
557 for (itemlist = undo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
558 it = (struct Item *)itemlist->data;
559 if (it->canvas_item != NULL) {
560 if (undo->layer != undo->layer2)
561 gnome_canvas_item_reparent(it->canvas_item, undo->layer->group);
562 gnome_canvas_item_move(it->canvas_item, -undo->val_x, -undo->val_y);
565 move_journal_items_by(undo->itemlist, -undo->val_x, -undo->val_y,
566 undo->layer2, undo->layer, undo->auxlist);
568 else if (undo->type == ITEM_RESIZESEL) {
569 resize_journal_items_by(undo->itemlist,
570 1/undo->scaling_x, 1/undo->scaling_y,
571 -undo->val_x/undo->scaling_x, -undo->val_y/undo->scaling_y);
573 else if (undo->type == ITEM_PASTE) {
574 for (itemlist = undo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
575 it = (struct Item *)itemlist->data;
576 gtk_object_destroy(GTK_OBJECT(it->canvas_item));
577 it->canvas_item = NULL;
578 undo->layer->items = g_list_remove(undo->layer->items, it);
579 undo->layer->nitems--;
582 else if (undo->type == ITEM_NEW_LAYER) {
583 // unmap the layer; keep the empty layer in memory
584 if (undo->layer->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->layer->group));
585 undo->layer->group = NULL;
586 undo->page->layers = g_list_remove(undo->page->layers, undo->layer);
587 undo->page->nlayers--;
588 do_switch_page(ui.pageno, FALSE, FALSE); // don't stay with bad cur_layer info
590 else if (undo->type == ITEM_DELETE_LAYER) {
591 // special case of -1: deleted the last layer, created a new one
592 if (undo->val == -1) {
593 if (undo->layer2->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->layer2->group));
594 undo->layer2->group = NULL;
595 undo->page->layers = g_list_remove(undo->page->layers, undo->layer2);
596 undo->page->nlayers--;
599 undo->layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
600 undo->page->group, gnome_canvas_group_get_type(), NULL);
601 lower_canvas_item_to(undo->page->group, GNOME_CANVAS_ITEM(undo->layer->group),
602 (undo->val >= 1) ? GNOME_CANVAS_ITEM(((struct Layer *)
603 g_list_nth_data(undo->page->layers, undo->val-1))->group) :
604 undo->page->bg->canvas_item);
605 undo->page->layers = g_list_insert(undo->page->layers, undo->layer,
606 (undo->val >= 0) ? undo->val:0);
607 undo->page->nlayers++;
609 for (itemlist = undo->layer->items; itemlist!=NULL; itemlist = itemlist->next)
610 make_canvas_item_one(undo->layer->group, (struct Item *)itemlist->data);
612 do_switch_page(ui.pageno, FALSE, FALSE); // show the restored layer & others...
614 else if (undo->type == ITEM_REPAINTSEL) {
615 for (itemlist = undo->itemlist, list = undo->auxlist; itemlist!=NULL;
616 itemlist = itemlist->next, list = list->next) {
617 it = (struct Item *)itemlist->data;
618 g_memmove(&tmp_brush, &(it->brush), sizeof(struct Brush));
619 g_memmove(&(it->brush), list->data, sizeof(struct Brush));
620 g_memmove(list->data, &tmp_brush, sizeof(struct Brush));
621 if (it->type == ITEM_STROKE && it->canvas_item != NULL) {
622 // remark: a variable-width item might have lost its variable-width
623 group = (GnomeCanvasGroup *) it->canvas_item->parent;
624 gtk_object_destroy(GTK_OBJECT(it->canvas_item));
625 make_canvas_item_one(group, it);
627 if (it->type == ITEM_TEXT && it->canvas_item != NULL)
628 gnome_canvas_item_set(it->canvas_item,
629 "fill-color-rgba", it->brush.color_rgba, NULL);
632 else if (undo->type == ITEM_TEXT_EDIT) {
634 undo->str = undo->item->text;
635 undo->item->text = tmpstr;
636 gnome_canvas_item_set(undo->item->canvas_item, "text", tmpstr, NULL);
637 update_item_bbox(undo->item);
639 else if (undo->type == ITEM_TEXT_ATTRIB) {
641 undo->str = undo->item->font_name;
642 undo->item->font_name = tmpstr;
644 undo->val_x = undo->item->font_size;
645 undo->item->font_size = tmp_x;
646 g_memmove(&tmp_brush, undo->brush, sizeof(struct Brush));
647 g_memmove(undo->brush, &(undo->item->brush), sizeof(struct Brush));
648 g_memmove(&(undo->item->brush), &tmp_brush, sizeof(struct Brush));
649 gnome_canvas_item_set(undo->item->canvas_item,
650 "fill-color-rgba", undo->item->brush.color_rgba, NULL);
651 update_text_item_displayfont(undo->item);
652 update_item_bbox(undo->item);
655 // move item from undo to redo stack
661 update_undo_redo_enabled();
662 if (u->multiop & MULTIOP_CONT_UNDO) on_editUndo_activate(NULL,NULL); // loop
667 on_editRedo_activate (GtkMenuItem *menuitem,
671 GList *list, *itemlist, *target;
672 struct UndoErasureData *erasure;
674 struct Brush tmp_brush;
675 struct Background *tmp_bg;
679 GnomeCanvasGroup *group;
682 if (redo == NULL) return; // nothing to redo!
683 reset_selection(); // safer
684 reset_recognizer(); // safer
685 if (redo->type == ITEM_STROKE || redo->type == ITEM_TEXT) {
686 // re-create the canvas_item
687 make_canvas_item_one(redo->layer->group, redo->item);
688 // reinsert the item on its layer
689 redo->layer->items = g_list_append(redo->layer->items, redo->item);
690 redo->layer->nitems++;
692 else if (redo->type == ITEM_ERASURE || redo->type == ITEM_RECOGNIZER) {
693 for (list = redo->erasurelist; list!=NULL; list = list->next) {
694 erasure = (struct UndoErasureData *)list->data;
695 target = g_list_find(redo->layer->items, erasure->item);
696 // re-create all the created items
697 for (itemlist = erasure->replacement_items; itemlist!=NULL; itemlist = itemlist->next) {
698 it = (struct Item *)itemlist->data;
699 make_canvas_item_one(redo->layer->group, it);
700 redo->layer->items = g_list_insert_before(redo->layer->items, target, it);
701 redo->layer->nitems++;
702 lower_canvas_item_to(redo->layer->group, it->canvas_item, erasure->item->canvas_item);
704 // re-delete the deleted one
705 gtk_object_destroy(GTK_OBJECT(erasure->item->canvas_item));
706 erasure->item->canvas_item = NULL;
707 redo->layer->items = g_list_delete_link(redo->layer->items, target);
708 redo->layer->nitems--;
711 else if (redo->type == ITEM_NEW_BG_ONE || redo->type == ITEM_NEW_BG_RESIZE
712 || redo->type == ITEM_PAPER_RESIZE) {
713 if (redo->type != ITEM_PAPER_RESIZE) {
715 tmp_bg = redo->page->bg;
716 redo->page->bg = redo->bg;
718 redo->page->bg->canvas_item = redo->bg->canvas_item;
719 redo->bg->canvas_item = NULL;
721 if (redo->type != ITEM_NEW_BG_ONE) {
722 tmp_x = redo->page->width;
723 tmp_y = redo->page->height;
724 redo->page->width = redo->val_x;
725 redo->page->height = redo->val_y;
728 make_page_clipbox(redo->page);
730 update_canvas_bg(redo->page);
731 do_switch_page(g_list_index(journal.pages, redo->page), TRUE, TRUE);
733 else if (redo->type == ITEM_NEW_DEFAULT_BG) {
734 tmp_bg = ui.default_page.bg;
735 ui.default_page.bg = redo->bg;
737 tmp_x = ui.default_page.width;
738 tmp_y = ui.default_page.height;
739 ui.default_page.width = redo->val_x;
740 ui.default_page.height = redo->val_y;
744 else if (redo->type == ITEM_NEW_PAGE) {
746 redo->page->bg->canvas_item = NULL;
747 redo->page->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
748 gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
749 make_page_clipbox(redo->page);
750 update_canvas_bg(redo->page);
751 l = (struct Layer *)redo->page->layers->data;
752 l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
753 redo->page->group, gnome_canvas_group_get_type(), NULL);
755 journal.pages = g_list_insert(journal.pages, redo->page, redo->val);
757 do_switch_page(redo->val, TRUE, TRUE);
759 else if (redo->type == ITEM_DELETE_PAGE) {
760 // unmap all the canvas items
761 gtk_object_destroy(GTK_OBJECT(redo->page->group));
762 redo->page->group = NULL;
763 redo->page->bg->canvas_item = NULL;
764 for (list = redo->page->layers; list!=NULL; list = list->next) {
765 l = (struct Layer *)list->data;
766 for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next)
767 ((struct Item *)itemlist->data)->canvas_item = NULL;
770 journal.pages = g_list_remove(journal.pages, redo->page);
772 if (ui.pageno > redo->val || ui.pageno == journal.npages) ui.pageno--;
774 // so do_switch_page() won't try to remap the layers of the defunct page
775 do_switch_page(ui.pageno, TRUE, TRUE);
777 else if (redo->type == ITEM_MOVESEL) {
778 for (itemlist = redo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
779 it = (struct Item *)itemlist->data;
780 if (it->canvas_item != NULL) {
781 if (redo->layer != redo->layer2)
782 gnome_canvas_item_reparent(it->canvas_item, redo->layer2->group);
783 gnome_canvas_item_move(it->canvas_item, redo->val_x, redo->val_y);
786 move_journal_items_by(redo->itemlist, redo->val_x, redo->val_y,
787 redo->layer, redo->layer2, NULL);
789 else if (redo->type == ITEM_RESIZESEL) {
790 resize_journal_items_by(redo->itemlist,
791 redo->scaling_x, redo->scaling_y, redo->val_x, redo->val_y);
793 else if (redo->type == ITEM_PASTE) {
794 for (itemlist = redo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
795 it = (struct Item *)itemlist->data;
796 make_canvas_item_one(redo->layer->group, it);
797 redo->layer->items = g_list_append(redo->layer->items, it);
798 redo->layer->nitems++;
801 else if (redo->type == ITEM_NEW_LAYER) {
802 redo->layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
803 redo->page->group, gnome_canvas_group_get_type(), NULL);
804 lower_canvas_item_to(redo->page->group, GNOME_CANVAS_ITEM(redo->layer->group),
805 (redo->val >= 1) ? GNOME_CANVAS_ITEM(((struct Layer *)
806 g_list_nth_data(redo->page->layers, redo->val-1))->group) :
807 redo->page->bg->canvas_item);
808 redo->page->layers = g_list_insert(redo->page->layers, redo->layer, redo->val);
809 redo->page->nlayers++;
810 do_switch_page(ui.pageno, FALSE, FALSE);
812 else if (redo->type == ITEM_DELETE_LAYER) {
813 gtk_object_destroy(GTK_OBJECT(redo->layer->group));
814 redo->layer->group = NULL;
815 for (list=redo->layer->items; list!=NULL; list=list->next)
816 ((struct Item *)list->data)->canvas_item = NULL;
817 redo->page->layers = g_list_remove(redo->page->layers, redo->layer);
818 redo->page->nlayers--;
819 if (redo->val == -1) {
820 redo->layer2->group = (GnomeCanvasGroup *)gnome_canvas_item_new(
821 redo->page->group, gnome_canvas_group_get_type(), NULL);
822 redo->page->layers = g_list_append(redo->page->layers, redo->layer2);
823 redo->page->nlayers++;
825 do_switch_page(ui.pageno, FALSE, FALSE);
827 else if (redo->type == ITEM_REPAINTSEL) {
828 for (itemlist = redo->itemlist, list = redo->auxlist; itemlist!=NULL;
829 itemlist = itemlist->next, list = list->next) {
830 it = (struct Item *)itemlist->data;
831 g_memmove(&tmp_brush, &(it->brush), sizeof(struct Brush));
832 g_memmove(&(it->brush), list->data, sizeof(struct Brush));
833 g_memmove(list->data, &tmp_brush, sizeof(struct Brush));
834 if (it->type == ITEM_STROKE && it->canvas_item != NULL) {
835 // remark: a variable-width item might have lost its variable-width
836 group = (GnomeCanvasGroup *) it->canvas_item->parent;
837 gtk_object_destroy(GTK_OBJECT(it->canvas_item));
838 make_canvas_item_one(group, it);
840 if (it->type == ITEM_TEXT && it->canvas_item != NULL)
841 gnome_canvas_item_set(it->canvas_item,
842 "fill-color-rgba", it->brush.color_rgba, NULL);
845 else if (redo->type == ITEM_TEXT_EDIT) {
847 redo->str = redo->item->text;
848 redo->item->text = tmpstr;
849 gnome_canvas_item_set(redo->item->canvas_item, "text", tmpstr, NULL);
850 update_item_bbox(redo->item);
852 else if (redo->type == ITEM_TEXT_ATTRIB) {
854 redo->str = redo->item->font_name;
855 redo->item->font_name = tmpstr;
857 redo->val_x = redo->item->font_size;
858 redo->item->font_size = tmp_x;
859 g_memmove(&tmp_brush, redo->brush, sizeof(struct Brush));
860 g_memmove(redo->brush, &(redo->item->brush), sizeof(struct Brush));
861 g_memmove(&(redo->item->brush), &tmp_brush, sizeof(struct Brush));
862 gnome_canvas_item_set(redo->item->canvas_item,
863 "fill-color-rgba", redo->item->brush.color_rgba, NULL);
864 update_text_item_displayfont(redo->item);
865 update_item_bbox(redo->item);
868 // move item from redo to undo stack
874 update_undo_redo_enabled();
875 if (u->multiop & MULTIOP_CONT_REDO) on_editRedo_activate(NULL,NULL); // loop
880 on_editCut_activate (GtkMenuItem *menuitem,
890 on_editCopy_activate (GtkMenuItem *menuitem,
899 on_editPaste_activate (GtkMenuItem *menuitem,
908 on_editDelete_activate (GtkMenuItem *menuitem,
917 on_viewContinuous_activate (GtkMenuItem *menuitem,
920 GtkAdjustment *v_adj;
924 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
925 if (ui.view_continuous) return;
926 ui.view_continuous = TRUE;
927 v_adj = gtk_layout_get_vadjustment(GTK_LAYOUT(canvas));
929 yscroll = gtk_adjustment_get_value(v_adj) - pg->voffset*ui.zoom;
931 gtk_adjustment_set_value(v_adj, yscroll + pg->voffset*ui.zoom);
933 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
938 on_viewOnePage_activate (GtkMenuItem *menuitem,
941 GtkAdjustment *v_adj;
944 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
945 if (!ui.view_continuous) return;
946 ui.view_continuous = FALSE;
947 v_adj = gtk_layout_get_vadjustment(GTK_LAYOUT(canvas));
948 yscroll = gtk_adjustment_get_value(v_adj) - ui.cur_page->voffset*ui.zoom;
950 gtk_adjustment_set_value(v_adj, yscroll + ui.cur_page->voffset*ui.zoom);
952 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
957 on_viewZoomIn_activate (GtkMenuItem *menuitem,
960 if (ui.zoom > MAX_ZOOM) return;
961 ui.zoom *= ui.zoom_step_factor;
962 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
963 rescale_text_items();
964 rescale_bg_pixmaps();
969 on_viewZoomOut_activate (GtkMenuItem *menuitem,
972 if (ui.zoom < MIN_ZOOM) return;
973 ui.zoom /= ui.zoom_step_factor;
974 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
975 rescale_text_items();
976 rescale_bg_pixmaps();
981 on_viewNormalSize_activate (GtkMenuItem *menuitem,
984 ui.zoom = DEFAULT_ZOOM;
985 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
986 rescale_text_items();
987 rescale_bg_pixmaps();
992 on_viewPageWidth_activate (GtkMenuItem *menuitem,
995 ui.zoom = (GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width;
996 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
997 rescale_text_items();
998 rescale_bg_pixmaps();
1003 on_viewFirstPage_activate (GtkMenuItem *menuitem,
1007 do_switch_page(0, TRUE, FALSE);
1012 on_viewPreviousPage_activate (GtkMenuItem *menuitem,
1016 if (ui.pageno == 0) return;
1017 do_switch_page(ui.pageno-1, TRUE, FALSE);
1022 on_viewNextPage_activate (GtkMenuItem *menuitem,
1026 if (ui.pageno == journal.npages-1) { // create a page at end
1027 on_journalNewPageEnd_activate(menuitem, user_data);
1030 do_switch_page(ui.pageno+1, TRUE, FALSE);
1035 on_viewLastPage_activate (GtkMenuItem *menuitem,
1039 do_switch_page(journal.npages-1, TRUE, FALSE);
1044 on_viewShowLayer_activate (GtkMenuItem *menuitem,
1048 if (ui.layerno == ui.cur_page->nlayers-1) return;
1051 ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
1052 gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group));
1053 update_page_stuff();
1058 on_viewHideLayer_activate (GtkMenuItem *menuitem,
1062 if (ui.layerno == -1) return;
1064 gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group));
1066 if (ui.layerno<0) ui.cur_layer = NULL;
1067 else ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
1068 update_page_stuff();
1073 on_journalNewPageBefore_activate (GtkMenuItem *menuitem,
1080 pg = new_page(ui.cur_page);
1081 journal.pages = g_list_insert(journal.pages, pg, ui.pageno);
1083 do_switch_page(ui.pageno, TRUE, TRUE);
1086 undo->type = ITEM_NEW_PAGE;
1087 undo->val = ui.pageno;
1093 on_journalNewPageAfter_activate (GtkMenuItem *menuitem,
1100 pg = new_page(ui.cur_page);
1101 journal.pages = g_list_insert(journal.pages, pg, ui.pageno+1);
1103 do_switch_page(ui.pageno+1, TRUE, TRUE);
1106 undo->type = ITEM_NEW_PAGE;
1107 undo->val = ui.pageno;
1113 on_journalNewPageEnd_activate (GtkMenuItem *menuitem,
1120 pg = new_page((struct Page *)g_list_last(journal.pages)->data);
1121 journal.pages = g_list_append(journal.pages, pg);
1123 do_switch_page(journal.npages-1, TRUE, TRUE);
1126 undo->type = ITEM_NEW_PAGE;
1127 undo->val = ui.pageno;
1133 on_journalDeletePage_activate (GtkMenuItem *menuitem,
1136 GList *layerlist, *itemlist;
1140 if (journal.npages == 1) return;
1142 reset_recognizer(); // safer
1144 undo->type = ITEM_DELETE_PAGE;
1145 undo->val = ui.pageno;
1146 undo->page = ui.cur_page;
1148 // unmap all the canvas items
1149 gtk_object_destroy(GTK_OBJECT(ui.cur_page->group));
1150 ui.cur_page->group = NULL;
1151 ui.cur_page->bg->canvas_item = NULL;
1152 for (layerlist = ui.cur_page->layers; layerlist!=NULL; layerlist = layerlist->next) {
1153 l = (struct Layer *)layerlist->data;
1154 for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next)
1155 ((struct Item *)itemlist->data)->canvas_item = NULL;
1159 journal.pages = g_list_remove(journal.pages, ui.cur_page);
1161 if (ui.pageno == journal.npages) ui.pageno--;
1163 // so do_switch_page() won't try to remap the layers of the defunct page
1164 do_switch_page(ui.pageno, TRUE, TRUE);
1169 on_journalNewLayer_activate (GtkMenuItem *menuitem,
1176 l = g_new(struct Layer, 1);
1179 l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
1180 ui.cur_page->group, gnome_canvas_group_get_type(), NULL);
1181 lower_canvas_item_to(ui.cur_page->group, GNOME_CANVAS_ITEM(l->group),
1182 (ui.cur_layer!=NULL)?(GNOME_CANVAS_ITEM(ui.cur_layer->group)):(ui.cur_page->bg->canvas_item));
1183 ui.cur_page->layers = g_list_insert(ui.cur_page->layers, l, ui.layerno+1);
1186 ui.cur_page->nlayers++;
1187 update_page_stuff();
1190 undo->type = ITEM_NEW_LAYER;
1191 undo->val = ui.layerno;
1193 undo->page = ui.cur_page;
1198 on_journalDeleteLayer_activate (GtkMenuItem *menuitem,
1204 if (ui.cur_layer == NULL) return;
1206 reset_recognizer(); // safer
1208 undo->type = ITEM_DELETE_LAYER;
1209 undo->val = ui.layerno;
1210 undo->layer = ui.cur_layer;
1211 undo->layer2 = NULL;
1212 undo->page = ui.cur_page;
1213 // delete all the canvas items
1214 gtk_object_destroy(GTK_OBJECT(ui.cur_layer->group));
1215 ui.cur_layer->group = NULL;
1216 for (list=ui.cur_layer->items; list!=NULL; list=list->next)
1217 ((struct Item *)list->data)->canvas_item = NULL;
1219 ui.cur_page->layers = g_list_remove(ui.cur_page->layers, ui.cur_layer);
1221 if (ui.cur_page->nlayers>=2) {
1222 ui.cur_page->nlayers--;
1224 if (ui.layerno<0) ui.cur_layer = NULL;
1225 else ui.cur_layer = (struct Layer *)g_list_nth_data(ui.cur_page->layers, ui.layerno);
1227 else { // special case: can't remove the last layer
1228 ui.cur_layer = g_new(struct Layer, 1);
1229 ui.cur_layer->items = NULL;
1230 ui.cur_layer->nitems = 0;
1231 ui.cur_layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
1232 ui.cur_page->group, gnome_canvas_group_get_type(), NULL);
1233 ui.cur_page->layers = g_list_append(NULL, ui.cur_layer);
1235 undo->layer2 = ui.cur_layer;
1238 update_page_stuff();
1243 on_journalFlatten_activate (GtkMenuItem *menuitem,
1250 // the paper sizes dialog
1252 GtkWidget *papersize_dialog;
1253 int papersize_std, papersize_unit;
1254 double papersize_width, papersize_height;
1255 gboolean papersize_need_init, papersize_width_valid, papersize_height_valid;
1257 #define STD_SIZE_A4 0
1258 #define STD_SIZE_A4R 1
1259 #define STD_SIZE_LETTER 2
1260 #define STD_SIZE_LETTER_R 3
1261 #define STD_SIZE_CUSTOM 4
1263 double unit_sizes[4] = {28.346, 72., 72./DISPLAY_DPI_DEFAULT, 1.};
1264 double std_widths[STD_SIZE_CUSTOM] = {595.27, 841.89, 612., 792.};
1265 double std_heights[STD_SIZE_CUSTOM] = {841.89, 595.27, 792., 612.};
1266 double std_units[STD_SIZE_CUSTOM] = {UNIT_CM, UNIT_CM, UNIT_IN, UNIT_IN};
1269 on_journalPaperSize_activate (GtkMenuItem *menuitem,
1277 papersize_dialog = create_papersizeDialog();
1278 papersize_width = ui.cur_page->width;
1279 papersize_height = ui.cur_page->height;
1280 papersize_unit = ui.default_unit;
1281 unit_sizes[UNIT_PX] = 1./DEFAULT_ZOOM;
1282 // if (ui.cur_page->bg->type == BG_PIXMAP) papersize_unit = UNIT_PX;
1283 papersize_std = STD_SIZE_CUSTOM;
1284 for (i=0;i<STD_SIZE_CUSTOM;i++)
1285 if (fabs(papersize_width - std_widths[i])<0.1 &&
1286 fabs(papersize_height - std_heights[i])<0.1)
1287 { papersize_std = i; papersize_unit = std_units[i]; }
1288 papersize_need_init = TRUE;
1289 papersize_width_valid = papersize_height_valid = TRUE;
1291 gtk_widget_show(papersize_dialog);
1292 on_comboStdSizes_changed(GTK_COMBO_BOX(g_object_get_data(
1293 G_OBJECT(papersize_dialog), "comboStdSizes")), NULL);
1294 gtk_dialog_set_default_response(GTK_DIALOG(papersize_dialog), GTK_RESPONSE_OK);
1296 response = gtk_dialog_run(GTK_DIALOG(papersize_dialog));
1297 gtk_widget_destroy(papersize_dialog);
1298 if (response != GTK_RESPONSE_OK) return;
1301 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
1302 if (ui.bg_apply_all_pages) pg = (struct Page *)pglist->data;
1304 if (ui.bg_apply_all_pages) {
1305 if (pglist->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
1306 if (pglist->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
1308 undo->type = ITEM_PAPER_RESIZE;
1310 undo->val_x = pg->width;
1311 undo->val_y = pg->height;
1312 if (papersize_width_valid) pg->width = papersize_width;
1313 if (papersize_height_valid) pg->height = papersize_height;
1314 make_page_clipbox(pg);
1315 update_canvas_bg(pg);
1316 if (!ui.bg_apply_all_pages) break;
1318 do_switch_page(ui.pageno, TRUE, TRUE);
1323 on_papercolorWhite_activate (GtkMenuItem *menuitem,
1327 process_papercolor_activate(menuitem, COLOR_WHITE, predef_bgcolors_rgba[COLOR_WHITE]);
1332 on_papercolorYellow_activate (GtkMenuItem *menuitem,
1336 process_papercolor_activate(menuitem, COLOR_YELLOW, predef_bgcolors_rgba[COLOR_YELLOW]);
1341 on_papercolorPink_activate (GtkMenuItem *menuitem,
1345 process_papercolor_activate(menuitem, COLOR_RED, predef_bgcolors_rgba[COLOR_RED]);
1350 on_papercolorOrange_activate (GtkMenuItem *menuitem,
1354 process_papercolor_activate(menuitem, COLOR_ORANGE, predef_bgcolors_rgba[COLOR_ORANGE]);
1359 on_papercolorBlue_activate (GtkMenuItem *menuitem,
1363 process_papercolor_activate(menuitem, COLOR_BLUE, predef_bgcolors_rgba[COLOR_BLUE]);
1368 on_papercolorGreen_activate (GtkMenuItem *menuitem,
1372 process_papercolor_activate(menuitem, COLOR_GREEN, predef_bgcolors_rgba[COLOR_GREEN]);
1377 on_papercolorOther_activate (GtkMenuItem *menuitem,
1381 GtkColorSelection *colorsel;
1387 dialog = gtk_color_selection_dialog_new(_("Pick a Paper Color"));
1388 colorsel = GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(dialog)->colorsel);
1389 if (ui.cur_page->bg->type == BG_SOLID) rgba = ui.cur_page->bg->color_rgba;
1390 else rgba = ui.default_page.bg->color_rgba;
1391 rgb_to_gdkcolor(rgba, &gdkcolor);
1392 gtk_color_selection_set_current_color(colorsel, &gdkcolor);
1394 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) {
1395 gtk_color_selection_get_current_color(colorsel, &gdkcolor);
1396 process_papercolor_activate(menuitem, COLOR_OTHER, gdkcolor_to_rgba(gdkcolor, 0xffff));
1398 gtk_widget_destroy(dialog);
1403 on_paperstylePlain_activate (GtkMenuItem *menuitem,
1407 process_paperstyle_activate(menuitem, RULING_NONE);
1412 on_paperstyleLined_activate (GtkMenuItem *menuitem,
1416 process_paperstyle_activate(menuitem, RULING_LINED);
1421 on_paperstyleRuled_activate (GtkMenuItem *menuitem,
1425 process_paperstyle_activate(menuitem, RULING_RULED);
1430 on_paperstyleGraph_activate (GtkMenuItem *menuitem,
1434 process_paperstyle_activate(menuitem, RULING_GRAPH);
1439 on_journalLoadBackground_activate (GtkMenuItem *menuitem,
1442 GtkWidget *dialog, *attach_opt;
1443 struct Background *bg;
1446 GList *bglist, *bglistiter;
1447 GtkFileFilter *filt_all, *filt_pix, *filt_pspdf;
1452 dialog = gtk_file_chooser_dialog_new(_("Open Background"), GTK_WINDOW (winMain),
1453 GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1454 GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
1455 #ifdef FILE_DIALOG_SIZE_BUGFIX
1456 gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
1459 filt_all = gtk_file_filter_new();
1460 gtk_file_filter_set_name(filt_all, _("All files"));
1461 gtk_file_filter_add_pattern(filt_all, "*");
1462 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
1464 #if GTK_CHECK_VERSION(2,6,0)
1466 if (!gtk_check_version(2, 6, 0)) {
1467 filt_pix = gtk_file_filter_new();
1468 gtk_file_filter_set_name(filt_pix, _("Bitmap files"));
1469 gtk_file_filter_add_pixbuf_formats(filt_pix);
1470 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pix);
1475 filt_pspdf = gtk_file_filter_new();
1476 gtk_file_filter_set_name(filt_pspdf, _("PS/PDF files (as bitmaps)"));
1477 gtk_file_filter_add_pattern(filt_pspdf, "*.ps");
1478 gtk_file_filter_add_pattern(filt_pspdf, "*.PS");
1479 gtk_file_filter_add_pattern(filt_pspdf, "*.pdf");
1480 gtk_file_filter_add_pattern(filt_pspdf, "*.PDF");
1481 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pspdf);
1483 attach_opt = gtk_check_button_new_with_label(_("Attach file to the journal"));
1484 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(attach_opt), FALSE);
1485 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER (dialog), attach_opt);
1487 if (ui.default_path!=NULL) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
1489 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
1490 gtk_widget_destroy(dialog);
1493 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1494 attach = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(attach_opt));
1495 gtk_widget_destroy(dialog);
1497 set_cursor_busy(TRUE);
1498 bg = attempt_load_pix_bg(filename, attach);
1499 if (bg != NULL) bglist = g_list_append(NULL, bg);
1500 else bglist = attempt_load_gv_bg(filename);
1501 set_cursor_busy(FALSE);
1503 if (bglist == NULL) {
1504 dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL,
1505 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
1506 _("Error opening background '%s'"), filename);
1507 gtk_dialog_run(GTK_DIALOG(dialog));
1508 gtk_widget_destroy(dialog);
1517 for (bglistiter = bglist, pageno = ui.pageno;
1518 bglistiter!=NULL; bglistiter = bglistiter->next, pageno++) {
1520 if (bglistiter->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
1521 if (bglistiter->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
1523 bg = (struct Background *)bglistiter->data;
1525 if (pageno == journal.npages) {
1526 undo->type = ITEM_NEW_PAGE;
1527 pg = new_page_with_bg(bg,
1528 gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale,
1529 gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale);
1530 journal.pages = g_list_append(journal.pages, pg);
1536 pg = g_list_nth_data(journal.pages, pageno);
1537 undo->type = ITEM_NEW_BG_RESIZE;
1540 bg->canvas_item = undo->bg->canvas_item;
1541 undo->bg->canvas_item = NULL;
1542 undo->val_x = pg->width;
1543 undo->val_y = pg->height;
1545 pg->width = gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale;
1546 pg->height = gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale;
1547 make_page_clipbox(pg);
1548 update_canvas_bg(pg);
1552 g_list_free(bglist);
1553 if (ui.zoom != DEFAULT_ZOOM) {
1554 ui.zoom = DEFAULT_ZOOM;
1555 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
1556 rescale_text_items();
1557 rescale_bg_pixmaps();
1559 do_switch_page(ui.pageno, TRUE, TRUE);
1563 on_journalScreenshot_activate (GtkMenuItem *menuitem,
1566 struct Background *bg;
1570 gtk_window_iconify(GTK_WINDOW(winMain)); // hide ourselves
1571 gdk_display_sync(gdk_display_get_default());
1573 if (ui.cursor!=NULL)
1574 gdk_cursor_unref(ui.cursor);
1575 ui.cursor = gdk_cursor_new(GDK_TCROSS);
1577 bg = attempt_screenshot_bg();
1579 gtk_window_deiconify(GTK_WINDOW(winMain));
1581 if (bg==NULL) return;
1584 undo->type = ITEM_NEW_BG_RESIZE;
1585 undo->page = ui.cur_page;
1586 undo->bg = ui.cur_page->bg;
1587 bg->canvas_item = undo->bg->canvas_item;
1588 undo->bg->canvas_item = NULL;
1589 undo->val_x = ui.cur_page->width;
1590 undo->val_y = ui.cur_page->height;
1592 ui.cur_page->bg = bg;
1593 ui.cur_page->width = gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale;
1594 ui.cur_page->height = gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale;
1596 make_page_clipbox(ui.cur_page);
1597 update_canvas_bg(ui.cur_page);
1599 if (ui.zoom != DEFAULT_ZOOM) {
1600 ui.zoom = DEFAULT_ZOOM;
1601 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
1602 rescale_text_items();
1603 rescale_bg_pixmaps();
1605 do_switch_page(ui.pageno, TRUE, TRUE);
1610 on_journalApplyAllPages_activate (GtkMenuItem *menuitem,
1616 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
1617 if (active == ui.bg_apply_all_pages) return;
1618 ui.bg_apply_all_pages = active;
1619 update_page_stuff();
1621 /* THIS IS THE OLD VERSION OF THE FEATURE -- APPLIED CURRENT BG TO ALL
1625 if (ui.cur_page->bg->type != BG_SOLID) return;
1627 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
1628 page = (struct Page *)pglist->data;
1630 undo->type = ITEM_NEW_BG_RESIZE;
1632 undo->bg = page->bg;
1633 undo->val_x = page->width;
1634 undo->val_y = page->height;
1635 if (pglist->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
1636 if (pglist->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
1637 page->bg = (struct Background *)g_memdup(ui.cur_page->bg, sizeof(struct Background));
1638 page->width = ui.cur_page->width;
1639 page->height = ui.cur_page->height;
1640 page->bg->canvas_item = undo->bg->canvas_item;
1641 undo->bg->canvas_item = NULL;
1643 make_page_clipbox(page);
1644 update_canvas_bg(page);
1646 do_switch_page(ui.pageno, TRUE, TRUE);
1653 on_toolsPen_activate (GtkMenuItem *menuitem,
1656 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1657 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1660 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1664 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1665 if (ui.toolno[ui.cur_mapping] == TOOL_PEN) return;
1667 ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1670 ui.toolno[ui.cur_mapping] = TOOL_PEN;
1671 ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
1672 ui.cur_brush->ruler = ui.default_brushes[TOOL_PEN].ruler;
1673 ui.cur_brush->recognizer = ui.default_brushes[TOOL_PEN].recognizer;
1674 update_mapping_linkings(TOOL_PEN);
1675 update_tool_buttons();
1677 update_color_menu();
1683 on_toolsEraser_activate (GtkMenuItem *menuitem,
1686 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1687 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1690 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1694 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1695 if (ui.toolno[ui.cur_mapping] == TOOL_ERASER) return;
1697 ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1700 ui.toolno[ui.cur_mapping] = TOOL_ERASER;
1701 ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_ERASER]);
1702 update_mapping_linkings(TOOL_ERASER);
1703 update_tool_buttons();
1705 update_color_menu();
1711 on_toolsHighlighter_activate (GtkMenuItem *menuitem,
1714 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1715 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1718 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1722 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1723 if (ui.toolno[ui.cur_mapping] == TOOL_HIGHLIGHTER) return;
1725 ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1728 ui.toolno[ui.cur_mapping] = TOOL_HIGHLIGHTER;
1729 ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_HIGHLIGHTER]);
1730 ui.cur_brush->ruler = ui.default_brushes[TOOL_HIGHLIGHTER].ruler;
1731 ui.cur_brush->recognizer = ui.default_brushes[TOOL_HIGHLIGHTER].recognizer;
1732 update_mapping_linkings(TOOL_HIGHLIGHTER);
1733 update_tool_buttons();
1735 update_color_menu();
1741 on_toolsText_activate (GtkMenuItem *menuitem,
1744 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1745 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1748 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1752 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1753 if (ui.toolno[ui.cur_mapping] == TOOL_TEXT) return;
1755 ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1757 ui.toolno[ui.cur_mapping] = TOOL_TEXT;
1758 ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
1759 update_mapping_linkings(-1);
1760 update_tool_buttons();
1762 update_color_menu();
1768 on_toolsSelectRegion_activate (GtkMenuItem *menuitem,
1776 on_toolsSelectRectangle_activate (GtkMenuItem *menuitem,
1779 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1780 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1783 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1787 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1788 if (ui.toolno[ui.cur_mapping] == TOOL_SELECTRECT) return;
1790 ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1792 ui.toolno[ui.cur_mapping] = TOOL_SELECTRECT;
1793 update_mapping_linkings(-1);
1794 update_tool_buttons();
1796 update_color_menu();
1802 on_toolsVerticalSpace_activate (GtkMenuItem *menuitem,
1805 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1806 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1809 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1813 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1814 if (ui.toolno[ui.cur_mapping] == TOOL_VERTSPACE) return;
1816 ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1819 ui.toolno[ui.cur_mapping] = TOOL_VERTSPACE;
1820 update_mapping_linkings(-1);
1821 update_tool_buttons();
1823 update_color_menu();
1829 on_colorBlack_activate (GtkMenuItem *menuitem,
1832 process_color_activate(menuitem, COLOR_BLACK, predef_colors_rgba[COLOR_BLACK]);
1837 on_colorBlue_activate (GtkMenuItem *menuitem,
1840 process_color_activate(menuitem, COLOR_BLUE, predef_colors_rgba[COLOR_BLUE]);
1845 on_colorRed_activate (GtkMenuItem *menuitem,
1848 process_color_activate(menuitem, COLOR_RED, predef_colors_rgba[COLOR_RED]);
1853 on_colorGreen_activate (GtkMenuItem *menuitem,
1856 process_color_activate(menuitem, COLOR_GREEN, predef_colors_rgba[COLOR_GREEN]);
1861 on_colorGray_activate (GtkMenuItem *menuitem,
1864 process_color_activate(menuitem, COLOR_GRAY, predef_colors_rgba[COLOR_GRAY]);
1869 on_colorLightBlue_activate (GtkMenuItem *menuitem,
1872 process_color_activate(menuitem, COLOR_LIGHTBLUE, predef_colors_rgba[COLOR_LIGHTBLUE]);
1877 on_colorLightGreen_activate (GtkMenuItem *menuitem,
1880 process_color_activate(menuitem, COLOR_LIGHTGREEN, predef_colors_rgba[COLOR_LIGHTGREEN]);
1885 on_colorMagenta_activate (GtkMenuItem *menuitem,
1888 process_color_activate(menuitem, COLOR_MAGENTA, predef_colors_rgba[COLOR_MAGENTA]);
1893 on_colorOrange_activate (GtkMenuItem *menuitem,
1896 process_color_activate(menuitem, COLOR_ORANGE, predef_colors_rgba[COLOR_ORANGE]);
1901 on_colorYellow_activate (GtkMenuItem *menuitem,
1904 process_color_activate(menuitem, COLOR_YELLOW, predef_colors_rgba[COLOR_YELLOW]);
1909 on_colorWhite_activate (GtkMenuItem *menuitem,
1912 process_color_activate(menuitem, COLOR_WHITE, predef_colors_rgba[COLOR_WHITE]);
1917 on_colorOther_activate (GtkMenuItem *menuitem,
1920 gtk_button_clicked(GTK_BUTTON(GET_COMPONENT("buttonColorChooser")));
1925 on_penthicknessVeryFine_activate (GtkMenuItem *menuitem,
1928 process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_VERYFINE);
1933 on_penthicknessFine_activate (GtkMenuItem *menuitem,
1936 process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_FINE);
1941 on_penthicknessMedium_activate (GtkMenuItem *menuitem,
1944 process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_MEDIUM);
1949 on_penthicknessThick_activate (GtkMenuItem *menuitem,
1952 process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_THICK);
1957 on_penthicknessVeryThick_activate (GtkMenuItem *menuitem,
1960 process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_VERYTHICK);
1965 on_eraserFine_activate (GtkMenuItem *menuitem,
1968 process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_FINE);
1973 on_eraserMedium_activate (GtkMenuItem *menuitem,
1976 process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_MEDIUM);
1981 on_eraserThick_activate (GtkMenuItem *menuitem,
1984 process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_THICK);
1989 on_eraserStandard_activate (GtkMenuItem *menuitem,
1992 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
1994 ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_STANDARD;
1995 update_mapping_linkings(TOOL_ERASER);
2000 on_eraserWhiteout_activate (GtkMenuItem *menuitem,
2003 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
2005 ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_WHITEOUT;
2006 update_mapping_linkings(TOOL_ERASER);
2011 on_eraserDeleteStrokes_activate (GtkMenuItem *menuitem,
2014 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
2016 ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_STROKES;
2017 update_mapping_linkings(TOOL_ERASER);
2022 on_highlighterFine_activate (GtkMenuItem *menuitem,
2025 process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_FINE);
2030 on_highlighterMedium_activate (GtkMenuItem *menuitem,
2033 process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_MEDIUM);
2038 on_highlighterThick_activate (GtkMenuItem *menuitem,
2041 process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_THICK);
2046 on_toolsTextFont_activate (GtkMenuItem *menuitem,
2052 dialog = gtk_font_selection_dialog_new(_("Select Font"));
2053 str = make_cur_font_name();
2054 gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dialog), str);
2056 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
2057 gtk_widget_destroy(dialog);
2060 str = gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(dialog));
2061 gtk_widget_destroy(dialog);
2062 process_font_sel(str);
2066 on_toolsDefaultPen_activate (GtkMenuItem *menuitem,
2072 g_memmove(&(ui.brushes[0][TOOL_PEN]), ui.default_brushes+TOOL_PEN, sizeof(struct Brush));
2073 ui.toolno[0] = TOOL_PEN;
2074 ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
2075 update_mapping_linkings(TOOL_PEN);
2076 update_tool_buttons();
2078 update_pen_props_menu();
2079 update_color_menu();
2085 on_toolsDefaultEraser_activate (GtkMenuItem *menuitem,
2091 g_memmove(&(ui.brushes[0][TOOL_ERASER]), ui.default_brushes+TOOL_ERASER, sizeof(struct Brush));
2092 ui.toolno[0] = TOOL_ERASER;
2093 ui.cur_brush = &(ui.brushes[0][TOOL_ERASER]);
2094 update_mapping_linkings(TOOL_ERASER);
2095 update_tool_buttons();
2097 update_eraser_props_menu();
2098 update_color_menu();
2104 on_toolsDefaultHighlighter_activate (GtkMenuItem *menuitem,
2110 g_memmove(&(ui.brushes[0][TOOL_HIGHLIGHTER]), ui.default_brushes+TOOL_HIGHLIGHTER, sizeof(struct Brush));
2111 ui.toolno[0] = TOOL_HIGHLIGHTER;
2112 ui.cur_brush = &(ui.brushes[0][TOOL_HIGHLIGHTER]);
2113 update_mapping_linkings(TOOL_HIGHLIGHTER);
2114 update_tool_buttons();
2116 update_highlighter_props_menu();
2117 update_color_menu();
2122 on_toolsDefaultText_activate (GtkMenuItem *menuitem,
2126 if (ui.toolno[0]!=TOOL_TEXT) end_text();
2128 ui.toolno[0] = TOOL_TEXT;
2129 ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
2130 ui.cur_brush->color_no = ui.default_brushes[TOOL_PEN].color_no;
2131 ui.cur_brush->color_rgba = ui.default_brushes[TOOL_PEN].color_rgba;
2132 g_free(ui.font_name);
2133 ui.font_name = g_strdup(ui.default_font_name);
2134 ui.font_size = ui.default_font_size;
2135 if (ui.cur_item_type == ITEM_TEXT) {
2136 refont_text_item(ui.cur_item, ui.font_name, ui.font_size);
2138 update_font_button();
2139 update_mapping_linkings(-1);
2140 update_tool_buttons();
2142 update_color_menu();
2148 on_toolsSetAsDefault_activate (GtkMenuItem *menuitem,
2153 if (ui.cur_mapping!=0 && !ui.button_switch_mapping) return;
2154 if (ui.toolno[ui.cur_mapping] < NUM_STROKE_TOOLS)
2155 g_memmove(ui.default_brushes+ui.toolno[ui.cur_mapping],
2156 &(ui.brushes[ui.cur_mapping][ui.toolno[ui.cur_mapping]]), sizeof(struct Brush));
2157 if (ui.toolno[ui.cur_mapping] == TOOL_TEXT) {
2158 if (ui.cur_item_type == ITEM_TEXT) {
2159 g_free(ui.font_name);
2160 ui.font_name = g_strdup(ui.cur_item->font_name);
2161 ui.font_size = ui.cur_item->font_size;
2163 else if (ui.selection!=NULL && ui.selection->items!=NULL &&
2164 ui.selection->items->next==NULL &&
2165 (it=(struct Item*)ui.selection->items->data)->type == ITEM_TEXT) {
2166 g_free(ui.font_name);
2167 ui.font_name = g_strdup(it->font_name);
2168 ui.font_size = it->font_size;
2170 g_free(ui.default_font_name);
2171 ui.default_font_name = g_strdup(ui.font_name);
2172 ui.default_font_size = ui.font_size;
2179 on_toolsRuler_activate (GtkMenuItem *menuitem,
2182 gboolean active, current;
2184 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
2185 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2187 active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
2189 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2190 current = (ui.toolno[ui.cur_mapping] == TOOL_PEN || ui.toolno[ui.cur_mapping] == TOOL_HIGHLIGHTER) && ui.cur_brush->ruler;
2191 if (active == current) return;
2195 if (ui.toolno[ui.cur_mapping]!=TOOL_PEN && ui.toolno[ui.cur_mapping]!=TOOL_HIGHLIGHTER) {
2197 ui.toolno[ui.cur_mapping] = TOOL_PEN;
2198 ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
2199 update_color_menu();
2200 update_tool_buttons();
2205 ui.cur_brush->ruler = active;
2206 if (active) ui.cur_brush->recognizer = FALSE;
2207 update_mapping_linkings(ui.toolno[ui.cur_mapping]);
2208 update_ruler_indicator();
2213 on_toolsReco_activate (GtkMenuItem *menuitem,
2216 gboolean active, current;
2218 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
2219 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2221 active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
2223 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2224 current = (ui.toolno[ui.cur_mapping] == TOOL_PEN || ui.toolno[ui.cur_mapping] == TOOL_HIGHLIGHTER) && ui.cur_brush->recognizer;
2225 if (active == current) return;
2229 if (ui.toolno[ui.cur_mapping]!=TOOL_PEN && ui.toolno[ui.cur_mapping]!=TOOL_HIGHLIGHTER) {
2231 ui.toolno[ui.cur_mapping] = TOOL_PEN;
2232 ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
2233 update_color_menu();
2234 update_tool_buttons();
2239 ui.cur_brush->recognizer = active;
2241 ui.cur_brush->ruler = FALSE;
2244 update_mapping_linkings(ui.toolno[ui.cur_mapping]);
2245 update_ruler_indicator();
2250 on_optionsSavePreferences_activate (GtkMenuItem *menuitem,
2254 save_config_to_file();
2259 on_helpIndex_activate (GtkMenuItem *menuitem,
2267 on_helpAbout_activate (GtkMenuItem *menuitem,
2270 GtkWidget *aboutDialog;
2271 GtkLabel *labelTitle;
2274 aboutDialog = create_aboutDialog ();
2275 labelTitle = GTK_LABEL(g_object_get_data(G_OBJECT(aboutDialog), "labelTitle"));
2276 gtk_label_set_markup(labelTitle,
2277 "<span size=\"xx-large\" weight=\"bold\">Xournal " VERSION_STRING "</span>");
2278 gtk_dialog_run (GTK_DIALOG(aboutDialog));
2279 gtk_widget_destroy(aboutDialog);
2284 on_buttonToolDefault_clicked (GtkToolButton *toolbutton,
2287 if (ui.toolno[0]==TOOL_TEXT) {
2288 on_toolsDefaultText_activate(NULL, NULL);
2293 if (ui.toolno[0] < NUM_STROKE_TOOLS) {
2294 g_memmove(&(ui.brushes[0][ui.toolno[0]]), ui.default_brushes+ui.toolno[0], sizeof(struct Brush));
2295 update_mapping_linkings(ui.toolno[0]);
2296 update_thickness_buttons();
2297 update_color_buttons();
2298 update_color_menu();
2299 if (ui.toolno[0] == TOOL_PEN) update_pen_props_menu();
2300 if (ui.toolno[0] == TOOL_ERASER) update_eraser_props_menu();
2301 if (ui.toolno[0] == TOOL_HIGHLIGHTER) update_highlighter_props_menu();
2308 on_buttonFine_clicked (GtkToolButton *toolbutton,
2311 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2312 process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[ui.cur_mapping], THICKNESS_FINE);
2317 on_buttonMedium_clicked (GtkToolButton *toolbutton,
2320 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2321 process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[ui.cur_mapping], THICKNESS_MEDIUM);
2326 on_buttonThick_clicked (GtkToolButton *toolbutton,
2329 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2330 process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[ui.cur_mapping], THICKNESS_THICK);
2335 on_canvas_button_press_event (GtkWidget *widget,
2336 GdkEventButton *event,
2340 gboolean page_change;
2341 struct Page *tmppage;
2346 GdkEvent scroll_event;
2349 printf("DEBUG: ButtonPress (%s) (x,y)=(%.2f,%.2f), button %d, modifier %x\n",
2350 event->device->name, event->x, event->y, event->button, event->state);
2353 // abort any page changes pending in the spin button, and take the focus
2354 gtk_spin_button_set_value(GTK_SPIN_BUTTON(GET_COMPONENT("spinPageNo")), ui.pageno+1);
2357 is_core = (event->device == gdk_device_get_core_pointer());
2358 if (!ui.use_xinput && !is_core) return FALSE;
2359 if (ui.use_xinput && is_core && ui.discard_corepointer) return FALSE;
2360 if (event->type != GDK_BUTTON_PRESS) return FALSE;
2361 // double-clicks may have broken axes member (free'd) due to a bug in GDK
2363 if (event->button > 3) { // scroll wheel events! don't paint...
2364 if (ui.use_xinput && !gtk_check_version(2, 17, 0) && event->button <= 7) {
2365 /* with GTK+ 2.17 and later, the entire widget hierarchy is xinput-aware,
2366 so the core button event gets discarded and the scroll event never
2367 gets processed by the main window. This is arguably a GTK+ bug.
2368 We work around it. */
2369 scroll_event.scroll.type = GDK_SCROLL;
2370 scroll_event.scroll.window = event->window;
2371 scroll_event.scroll.send_event = event->send_event;
2372 scroll_event.scroll.time = event->time;
2373 scroll_event.scroll.x = event->x;
2374 scroll_event.scroll.y = event->y;
2375 scroll_event.scroll.state = event->state;
2376 scroll_event.scroll.device = event->device;
2377 scroll_event.scroll.x_root = event->x_root;
2378 scroll_event.scroll.y_root = event->y_root;
2379 if (event->button == 4) scroll_event.scroll.direction = GDK_SCROLL_UP;
2380 else if (event->button == 5) scroll_event.scroll.direction = GDK_SCROLL_DOWN;
2381 else if (event->button == 6) scroll_event.scroll.direction = GDK_SCROLL_LEFT;
2382 else scroll_event.scroll.direction = GDK_SCROLL_RIGHT;
2383 gtk_widget_event(GET_COMPONENT("scrolledwindowMain"), &scroll_event);
2387 if ((event->state & (GDK_CONTROL_MASK|GDK_MOD1_MASK)) != 0) return FALSE;
2388 // no control-clicking or alt-clicking
2389 if (!is_core) gdk_device_get_state(event->device, event->window, event->axes, NULL);
2390 // synaptics touchpads send bogus axis values with ButtonDown
2392 fix_xinput_coords((GdkEvent *)event);
2394 if (!finite_sized(event->x) || !finite_sized(event->y)) return FALSE; // Xorg 7.3 bug
2396 if (ui.cur_item_type == ITEM_TEXT) {
2397 if (!is_event_within_textview(event)) end_text();
2400 if (ui.cur_item_type == ITEM_STROKE && ui.is_corestroke && !is_core &&
2401 ui.cur_path.num_points == 1) {
2402 // Xorg 7.3+ sent core event before XInput event: fix initial point
2403 ui.is_corestroke = FALSE;
2404 get_pointer_coords((GdkEvent *)event, ui.cur_path.coords);
2406 if (ui.cur_item_type != ITEM_NONE) return FALSE; // we're already doing something
2408 // if button_switch_mapping enabled, button 2 or 3 clicks only switch mapping
2409 if (ui.button_switch_mapping && event->button > 1) {
2410 ui.which_unswitch_button = event->button;
2411 switch_mapping(event->button-1);
2415 ui.is_corestroke = is_core;
2416 ui.stroke_device = event->device;
2418 if (ui.use_erasertip && event->device->source == GDK_SOURCE_ERASER)
2419 mapping = NUM_BUTTONS;
2420 else if (ui.button_switch_mapping) {
2421 mapping = ui.cur_mapping;
2422 if (!mapping && (event->state & GDK_BUTTON2_MASK)) mapping = 1;
2423 if (!mapping && (event->state & GDK_BUTTON3_MASK)) mapping = 2;
2425 else mapping = event->button-1;
2427 // check whether we're in a page
2428 page_change = FALSE;
2429 tmppage = ui.cur_page;
2430 get_pointer_coords((GdkEvent *)event, pt);
2431 while (ui.view_continuous && (pt[1] < - VIEW_CONTINUOUS_SKIP)) {
2432 if (ui.pageno == 0) break;
2435 tmppage = g_list_nth_data(journal.pages, ui.pageno);
2436 pt[1] += tmppage->height + VIEW_CONTINUOUS_SKIP;
2438 while (ui.view_continuous && (pt[1] > tmppage->height + VIEW_CONTINUOUS_SKIP)) {
2439 if (ui.pageno == journal.npages-1) break;
2440 pt[1] -= tmppage->height + VIEW_CONTINUOUS_SKIP;
2443 tmppage = g_list_nth_data(journal.pages, ui.pageno);
2445 if (page_change) do_switch_page(ui.pageno, FALSE, FALSE);
2447 // can't paint on the background...
2449 if (ui.cur_layer == NULL) {
2451 dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL,
2452 GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("Drawing is not allowed on the "
2453 "background layer.\n Switching to Layer 1."));
2454 gtk_dialog_run(GTK_DIALOG(dialog));
2455 gtk_widget_destroy(dialog);
2456 on_viewShowLayer_activate(NULL, NULL);
2460 // switch mappings if needed
2462 ui.which_mouse_button = event->button;
2463 switch_mapping(mapping);
2468 // in text tool, clicking in a text area edits it
2469 if (ui.toolno[mapping] == TOOL_TEXT) {
2470 item = click_is_in_text(ui.cur_layer, pt[0], pt[1]);
2473 start_text((GdkEvent *)event, item);
2478 // if this can be a selection move or resize, then it takes precedence over anything else
2479 if (start_resizesel((GdkEvent *)event)) return FALSE;
2480 if (start_movesel((GdkEvent *)event)) return FALSE;
2482 if (ui.toolno[mapping] != TOOL_SELECTREGION && ui.toolno[mapping] != TOOL_SELECTRECT)
2485 // process the event
2487 if (ui.toolno[mapping] == TOOL_HAND) {
2488 ui.cur_item_type = ITEM_HAND;
2489 get_pointer_coords((GdkEvent *)event, ui.hand_refpt);
2490 ui.hand_refpt[0] += ui.cur_page->hoffset;
2491 ui.hand_refpt[1] += ui.cur_page->voffset;
2493 else if (ui.toolno[mapping] == TOOL_PEN || ui.toolno[mapping] == TOOL_HIGHLIGHTER ||
2494 (ui.toolno[mapping] == TOOL_ERASER && ui.cur_brush->tool_options == TOOLOPT_ERASER_WHITEOUT)) {
2495 create_new_stroke((GdkEvent *)event);
2497 else if (ui.toolno[mapping] == TOOL_ERASER) {
2498 ui.cur_item_type = ITEM_ERASURE;
2499 do_eraser((GdkEvent *)event, ui.cur_brush->thickness/2,
2500 ui.cur_brush->tool_options == TOOLOPT_ERASER_STROKES);
2502 else if (ui.toolno[mapping] == TOOL_SELECTRECT) {
2503 start_selectrect((GdkEvent *)event);
2505 else if (ui.toolno[mapping] == TOOL_VERTSPACE) {
2506 start_vertspace((GdkEvent *)event);
2508 else if (ui.toolno[mapping] == TOOL_TEXT) {
2509 start_text((GdkEvent *)event, NULL);
2516 on_canvas_button_release_event (GtkWidget *widget,
2517 GdkEventButton *event,
2523 printf("DEBUG: ButtonRelease (%s) (x,y)=(%.2f,%.2f), button %d, modifier %x\n",
2524 event->device->name, event->x, event->y, event->button, event->state);
2527 is_core = (event->device == gdk_device_get_core_pointer());
2528 if (!ui.use_xinput && !is_core) return FALSE;
2529 if (ui.use_xinput && is_core && !ui.is_corestroke) return FALSE;
2530 if (!is_core) fix_xinput_coords((GdkEvent *)event);
2532 if (event->button != ui.which_mouse_button &&
2533 event->button != ui.which_unswitch_button)
2536 if (ui.cur_item_type == ITEM_STROKE) {
2538 if (ui.cur_brush->recognizer) recognize_patterns();
2540 else if (ui.cur_item_type == ITEM_ERASURE) {
2543 else if (ui.cur_item_type == ITEM_SELECTRECT) {
2544 finalize_selectrect();
2546 else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2549 else if (ui.cur_item_type == ITEM_RESIZESEL) {
2550 finalize_resizesel();
2552 else if (ui.cur_item_type == ITEM_HAND) {
2553 ui.cur_item_type = ITEM_NONE;
2556 if (!ui.which_unswitch_button || event->button == ui.which_unswitch_button)
2557 switch_mapping(0); // will reset ui.which_unswitch_button
2564 on_canvas_enter_notify_event (GtkWidget *widget,
2565 GdkEventCrossing *event,
2572 printf("DEBUG: enter notify\n");
2574 /* re-enable input devices after they've been emergency-disabled
2576 if (!gtk_check_version(2, 17, 0)) {
2578 gdk_error_trap_push();
2579 for (dev_list = gdk_devices_list(); dev_list != NULL; dev_list = dev_list->next) {
2580 dev = GDK_DEVICE(dev_list->data);
2581 gdk_device_set_mode(dev, GDK_MODE_SCREEN);
2583 ui.is_corestroke = ui.saved_is_corestroke;
2585 gdk_error_trap_pop();
2591 on_canvas_leave_notify_event (GtkWidget *widget,
2592 GdkEventCrossing *event,
2599 printf("DEBUG: leave notify (mode=%d, details=%d)\n", event->mode, event->detail);
2601 /* emergency disable XInput to avoid segfaults (GTK+ 2.17) or
2602 interface non-responsiveness (GTK+ 2.18) */
2603 if (!gtk_check_version(2, 17, 0)) {
2605 gdk_error_trap_push();
2606 for (dev_list = gdk_devices_list(); dev_list != NULL; dev_list = dev_list->next) {
2607 dev = GDK_DEVICE(dev_list->data);
2608 gdk_device_set_mode(dev, GDK_MODE_DISABLED);
2610 ui.saved_is_corestroke = ui.is_corestroke;
2611 ui.is_corestroke = TRUE;
2613 gdk_error_trap_pop();
2620 on_canvas_expose_event (GtkWidget *widget,
2621 GdkEventExpose *event,
2624 if (ui.view_continuous && ui.progressive_bg) rescale_bg_pixmaps();
2630 on_canvas_key_press_event (GtkWidget *widget,
2637 // Esc leaves text edition, or leaves fullscreen mode
2638 if (event->keyval == GDK_Escape) {
2639 if (ui.cur_item_type == ITEM_TEXT) {
2643 else if (ui.fullscreen) {
2644 do_fullscreen(FALSE);
2650 /* In single page mode, switch pages with PgUp/PgDn (or Up/Dn)
2651 when there's nowhere else to go. */
2652 pgheight = GTK_WIDGET(canvas)->allocation.height;
2653 adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(GET_COMPONENT("scrolledwindowMain")));
2655 if (event->keyval == GDK_Page_Down || event->keyval == GDK_Down) {
2656 if (!ui.view_continuous &&
2657 (0.96 * ui.zoom * ui.cur_page->height < pgheight ||
2658 adj->value == adj->upper-pgheight))
2661 if (ui.pageno < journal.npages-1)
2662 do_switch_page(ui.pageno+1, TRUE, FALSE);
2665 if (adj->value == adj->upper-pgheight) return TRUE; // don't send focus away
2668 if (event->keyval == GDK_Page_Up || event->keyval == GDK_Up) {
2669 if (!ui.view_continuous &&
2670 (0.96 * ui.zoom * ui.cur_page->height < pgheight ||
2671 adj->value == adj->lower))
2674 if (ui.pageno != 0) {
2675 do_switch_page(ui.pageno-1, TRUE, FALSE);
2676 gtk_adjustment_set_value(adj, adj->upper-pgheight);
2680 if (adj->value == adj->lower) return TRUE; // don't send focus away
2688 on_canvas_motion_notify_event (GtkWidget *widget,
2689 GdkEventMotion *event,
2692 gboolean looks_wrong, is_core;
2694 GdkModifierType mask;
2696 /* we don't care about this event unless some operation is in progress;
2697 or if there's a selection (then we might want to change the mouse
2698 cursor to indicate the possibility of resizing) */
2699 if (ui.cur_item_type == ITEM_NONE && ui.selection==NULL) return FALSE;
2700 if (ui.cur_item_type == ITEM_TEXT) return FALSE;
2702 is_core = (event->device == gdk_device_get_core_pointer());
2703 if (!ui.use_xinput && !is_core) return FALSE;
2704 if (!is_core) fix_xinput_coords((GdkEvent *)event);
2705 if (!finite_sized(event->x) || !finite_sized(event->y)) return FALSE; // Xorg 7.3 bug
2707 if (ui.selection!=NULL && ui.cur_item_type == ITEM_NONE) {
2708 get_pointer_coords((GdkEvent *)event, pt);
2709 update_cursor_for_resize(pt);
2713 if (ui.use_xinput && is_core && !ui.is_corestroke) return FALSE;
2714 if (!is_core) ui.is_corestroke = FALSE;
2717 printf("DEBUG: MotionNotify (%s) (x,y)=(%.2f,%.2f), modifier %x\n",
2718 is_core?"core":"xinput", event->x, event->y, event->state);
2721 looks_wrong = !(event->state & (1<<(7+ui.which_mouse_button)));
2723 gdk_device_get_state(ui.stroke_device, event->window, NULL, &mask);
2724 looks_wrong = !(mask & (1<<(7+ui.which_mouse_button)));
2727 if (looks_wrong) { /* mouse button shouldn't be up... give up */
2728 if (ui.cur_item_type == ITEM_STROKE) {
2730 if (ui.cur_brush->recognizer) recognize_patterns();
2732 else if (ui.cur_item_type == ITEM_ERASURE) {
2735 else if (ui.cur_item_type == ITEM_SELECTRECT) {
2736 finalize_selectrect();
2738 else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2741 else if (ui.cur_item_type == ITEM_RESIZESEL) {
2742 finalize_resizesel();
2744 else if (ui.cur_item_type == ITEM_HAND) {
2745 ui.cur_item_type = ITEM_NONE;
2751 if (ui.cur_item_type == ITEM_STROKE) {
2752 continue_stroke((GdkEvent *)event);
2754 else if (ui.cur_item_type == ITEM_ERASURE) {
2755 do_eraser((GdkEvent *)event, ui.cur_brush->thickness/2,
2756 ui.cur_brush->tool_options == TOOLOPT_ERASER_STROKES);
2758 else if (ui.cur_item_type == ITEM_SELECTRECT) {
2759 get_pointer_coords((GdkEvent *)event, pt);
2760 ui.selection->bbox.right = pt[0];
2761 ui.selection->bbox.bottom = pt[1];
2762 gnome_canvas_item_set(ui.selection->canvas_item,
2763 "x2", pt[0], "y2", pt[1], NULL);
2765 else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2766 continue_movesel((GdkEvent *)event);
2768 else if (ui.cur_item_type == ITEM_RESIZESEL) {
2769 continue_resizesel((GdkEvent *)event);
2771 else if (ui.cur_item_type == ITEM_HAND) {
2772 do_hand((GdkEvent *)event);
2779 on_comboLayer_changed (GtkComboBox *combobox,
2784 if (ui.in_update_page_stuff) return; // avoid a bad retroaction
2788 val = gtk_combo_box_get_active(combobox);
2789 if (val == -1) return;
2790 val = ui.cur_page->nlayers-1-val;
2791 if (val == ui.layerno) return;
2794 while (val>ui.layerno) {
2796 ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
2797 gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group));
2799 while (val<ui.layerno) {
2800 gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group));
2802 if (ui.layerno<0) ui.cur_layer = NULL;
2803 else ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
2805 update_page_stuff();
2810 on_winMain_delete_event (GtkWidget *widget,
2815 if (ok_to_close()) gtk_main_quit();
2821 on_optionsUseXInput_activate (GtkMenuItem *menuitem,
2825 ui.allow_xinput = ui.use_xinput =
2826 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2828 /* HOW THINGS USED TO BE:
2830 We'd like on_canvas_... to get BOTH core and xinput events. Up to
2831 GTK+ 2.16 this is achieved by making only the canvas's parent
2832 GdkWindow xinput-aware, rather than the entire hierarchy.
2833 Otherwise, the proximity detection code in GDK is broken and
2834 we'll lose core events.
2836 Up to GTK+ 2.10, gtk_widget_set_extension_events() only sets
2837 extension events for the widget's main window itself; in GTK+ 2.11
2838 also traverses GDK child windows that belong to the widget
2839 and sets their extension events too. We want to avoid that.
2840 So we use gdk_input_set_extension_events() directly on the canvas.
2842 As much as possible, we'd like to keep doing this, though GTK+ 2.17
2843 is making our life harder (crasher bugs require us to disable XInput
2844 while editing text or using the layers combo box, but disabling
2845 XInput while in a XInput-aware window causes the interface to become
2850 if (!gtk_check_version(2, 17, 0)) {
2852 /* GTK+ 2.17 and later: everybody shares a single native window,
2853 so we'll never get any core events, and we might as well set
2854 extension events the way we're supposed to. Doing so helps solve
2855 crasher bugs in 2.17, and prevents us from losing two-button
2857 gtk_widget_set_extension_events(GTK_WIDGET (canvas),
2858 ui.use_xinput?GDK_EXTENSION_EVENTS_ALL:GDK_EXTENSION_EVENTS_NONE);
2862 /* GTK+ 2.16 and earlier: we only activate extension events on the
2863 canvas's parent GdkWindow. This allows us to keep receiving core
2865 gdk_input_set_extension_events(GTK_WIDGET(canvas)->window,
2866 GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK,
2867 ui.use_xinput?GDK_EXTENSION_EVENTS_ALL:GDK_EXTENSION_EVENTS_NONE);
2872 update_mappings_menu();
2876 on_vscroll_changed (GtkAdjustment *adjustment,
2879 gboolean need_update;
2880 double viewport_top, viewport_bottom;
2881 struct Page *tmppage;
2883 if (!ui.view_continuous) return;
2885 if (ui.progressive_bg) rescale_bg_pixmaps();
2886 need_update = FALSE;
2887 viewport_top = adjustment->value / ui.zoom;
2888 viewport_bottom = (adjustment->value + adjustment->page_size) / ui.zoom;
2889 tmppage = ui.cur_page;
2890 while (viewport_top > tmppage->voffset + tmppage->height) {
2891 if (ui.pageno == journal.npages-1) break;
2894 tmppage = g_list_nth_data(journal.pages, ui.pageno);
2896 while (viewport_bottom < tmppage->voffset) {
2897 if (ui.pageno == 0) break;
2900 tmppage = g_list_nth_data(journal.pages, ui.pageno);
2904 do_switch_page(ui.pageno, FALSE, FALSE);
2910 on_spinPageNo_value_changed (GtkSpinButton *spinbutton,
2915 if (ui.in_update_page_stuff) return; // avoid a bad retroaction
2917 /* in preparation for end_text(), send focus to the canvas if it's not ours.
2918 (avoid issues with Gtk trying to send focus to the dead text widget) */
2920 if (!GTK_WIDGET_HAS_FOCUS(spinbutton))
2921 gtk_widget_grab_focus(GTK_WIDGET(canvas));
2924 val = gtk_spin_button_get_value_as_int(spinbutton) - 1;
2926 if (val == journal.npages) { // create a page at end
2927 on_journalNewPageEnd_activate(NULL, NULL);
2931 if (val == ui.pageno) return;
2932 if (val < 0) val = 0;
2933 if (val > journal.npages-1) val = journal.npages-1;
2934 do_switch_page(val, TRUE, FALSE);
2939 on_journalDefaultBackground_activate (GtkMenuItem *menuitem,
2949 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
2950 if (ui.bg_apply_all_pages) pg = (struct Page *)pglist->data;
2952 if (ui.bg_apply_all_pages) {
2953 if (pglist->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
2954 if (pglist->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
2956 undo->type = ITEM_NEW_BG_RESIZE;
2959 undo->val_x = pg->width;
2960 undo->val_y = pg->height;
2961 pg->bg = (struct Background *)g_memdup(ui.default_page.bg, sizeof(struct Background));
2962 pg->width = ui.default_page.width;
2963 pg->height = ui.default_page.height;
2964 pg->bg->canvas_item = undo->bg->canvas_item;
2965 undo->bg->canvas_item = NULL;
2967 make_page_clipbox(pg);
2968 update_canvas_bg(pg);
2969 if (!ui.bg_apply_all_pages) break;
2971 do_switch_page(ui.pageno, TRUE, TRUE);
2976 on_journalSetAsDefault_activate (GtkMenuItem *menuitem,
2979 if (ui.cur_page->bg->type != BG_SOLID) return;
2983 undo->type = ITEM_NEW_DEFAULT_BG;
2984 undo->val_x = ui.default_page.width;
2985 undo->val_y = ui.default_page.height;
2986 undo->bg = ui.default_page.bg;
2988 ui.default_page.width = ui.cur_page->width;
2989 ui.default_page.height = ui.cur_page->height;
2990 ui.default_page.bg = (struct Background *)g_memdup(ui.cur_page->bg, sizeof(struct Background));
2991 ui.default_page.bg->canvas_item = NULL;
2996 on_comboStdSizes_changed (GtkComboBox *combobox,
3000 GtkComboBox *comboUnit;
3004 if (papersize_need_init) {
3005 gtk_combo_box_set_active(combobox, papersize_std);
3006 papersize_need_init = FALSE;
3008 val = gtk_combo_box_get_active(combobox);
3009 if (val == -1 || val == papersize_std) return;
3010 papersize_std = val;
3011 if (val == STD_SIZE_CUSTOM) return;
3012 papersize_unit = std_units[val];
3013 papersize_width = std_widths[val];
3014 papersize_height = std_heights[val];
3016 comboUnit = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboUnit"));
3017 gtk_combo_box_set_active(comboUnit, papersize_unit);
3018 entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryWidth"));
3019 g_snprintf(text, 20, "%.2f", papersize_width/unit_sizes[papersize_unit]);
3020 if (g_str_has_suffix(text, ".00"))
3021 g_snprintf(text, 20, "%d", (int) (papersize_width/unit_sizes[papersize_unit]));
3022 gtk_entry_set_text(entry, text);
3023 entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryHeight"));
3024 g_snprintf(text, 20, "%.2f", papersize_height/unit_sizes[papersize_unit]);
3025 if (g_str_has_suffix(text, ".00"))
3026 g_snprintf(text, 20, "%d", (int) (papersize_height/unit_sizes[papersize_unit]));
3027 gtk_entry_set_text(entry, text);
3032 on_entryWidth_changed (GtkEditable *editable,
3038 GtkComboBox *comboStdSizes;
3040 text = gtk_entry_get_text(GTK_ENTRY(editable));
3041 val = strtod(text, &ptr);
3042 papersize_width_valid = (*ptr == 0 && val > 0.);
3043 if (!papersize_width_valid) return; // invalid entry
3044 val *= unit_sizes[papersize_unit];
3045 if (fabs(val - papersize_width) < 0.1) return; // no change
3046 papersize_std = STD_SIZE_CUSTOM;
3047 papersize_width = val;
3048 comboStdSizes = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboStdSizes"));
3049 gtk_combo_box_set_active(comboStdSizes, papersize_std);
3054 on_entryHeight_changed (GtkEditable *editable,
3060 GtkComboBox *comboStdSizes;
3062 text = gtk_entry_get_text(GTK_ENTRY(editable));
3063 val = strtod(text, &ptr);
3064 papersize_height_valid = (*ptr == 0 && val > 0.);
3065 if (!papersize_height_valid) return; // invalid entry
3066 val *= unit_sizes[papersize_unit];
3067 if (fabs(val - papersize_height) < 0.1) return; // no change
3068 papersize_std = STD_SIZE_CUSTOM;
3069 papersize_height = val;
3070 comboStdSizes = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboStdSizes"));
3071 gtk_combo_box_set_active(comboStdSizes, papersize_std);
3076 on_comboUnit_changed (GtkComboBox *combobox,
3083 val = gtk_combo_box_get_active(combobox);
3084 if (val == -1 || val == papersize_unit) return;
3085 papersize_unit = val;
3086 entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryWidth"));
3087 if (papersize_width_valid) {
3088 g_snprintf(text, 20, "%.2f", papersize_width/unit_sizes[papersize_unit]);
3089 if (g_str_has_suffix(text, ".00"))
3090 g_snprintf(text, 20, "%d", (int) (papersize_width/unit_sizes[papersize_unit]));
3092 gtk_entry_set_text(entry, text);
3093 if (papersize_height_valid) {
3094 entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryHeight"));
3095 g_snprintf(text, 20, "%.2f", papersize_height/unit_sizes[papersize_unit]);
3096 if (g_str_has_suffix(text, ".00"))
3097 g_snprintf(text, 20, "%d", (int) (papersize_height/unit_sizes[papersize_unit]));
3099 gtk_entry_set_text(entry, text);
3104 on_viewFullscreen_activate (GtkMenuItem *menuitem,
3109 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
3110 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3112 active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
3114 if (active == ui.fullscreen) return;
3115 do_fullscreen(active);
3120 on_optionsButtonMappings_activate (GtkMenuItem *menuitem,
3125 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3126 update_mappings_menu();
3131 on_optionsProgressiveBG_activate (GtkMenuItem *menuitem,
3136 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3137 if (ui.progressive_bg == active) return;
3139 ui.progressive_bg = active;
3140 if (!ui.progressive_bg) rescale_bg_pixmaps();
3145 on_mru_activate (GtkMenuItem *menuitem,
3153 if (!ok_to_close()) return; // user aborted on save confirmation
3155 for (which = 0 ; which < MRU_SIZE; which++) {
3156 if (ui.mrumenu[which] == GTK_WIDGET(menuitem)) break;
3158 if (which == MRU_SIZE || ui.mru[which] == NULL) return; // not found...
3160 set_cursor_busy(TRUE);
3161 success = open_journal(ui.mru[which]);
3162 set_cursor_busy(FALSE);
3163 if (success) return;
3166 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
3167 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening file '%s'"), ui.mru[which]);
3168 gtk_dialog_run(GTK_DIALOG(dialog));
3169 gtk_widget_destroy(dialog);
3170 delete_mru_entry(which);
3175 on_button2Pen_activate (GtkMenuItem *menuitem,
3178 process_mapping_activate(menuitem, 1, TOOL_PEN);
3183 on_button2Eraser_activate (GtkMenuItem *menuitem,
3186 process_mapping_activate(menuitem, 1, TOOL_ERASER);
3191 on_button2Highlighter_activate (GtkMenuItem *menuitem,
3194 process_mapping_activate(menuitem, 1, TOOL_HIGHLIGHTER);
3199 on_button2Text_activate (GtkMenuItem *menuitem,
3202 process_mapping_activate(menuitem, 1, TOOL_TEXT);
3207 on_button2SelectRegion_activate (GtkMenuItem *menuitem,
3210 process_mapping_activate(menuitem, 1, TOOL_SELECTREGION);
3215 on_button2SelectRectangle_activate (GtkMenuItem *menuitem,
3218 process_mapping_activate(menuitem, 1, TOOL_SELECTRECT);
3223 on_button2VerticalSpace_activate (GtkMenuItem *menuitem,
3226 process_mapping_activate(menuitem, 1, TOOL_VERTSPACE);
3231 on_button2LinkBrush_activate (GtkMenuItem *menuitem,
3236 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3238 ui.linked_brush[1] = BRUSH_LINKED;
3239 for (i=0;i<NUM_STROKE_TOOLS;i++) update_mapping_linkings(i);
3244 on_button2CopyBrush_activate (GtkMenuItem *menuitem,
3247 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3249 if (ui.toolno[1] >= NUM_STROKE_TOOLS) {
3250 ui.linked_brush[1] = BRUSH_STATIC;
3251 update_mappings_menu_linkings();
3254 ui.linked_brush[1] = BRUSH_COPIED;
3255 g_memmove(&(ui.brushes[1][ui.toolno[1]]), &(ui.brushes[0][ui.toolno[1]]), sizeof(struct Brush));
3260 on_button3Pen_activate (GtkMenuItem *menuitem,
3263 process_mapping_activate(menuitem, 2, TOOL_PEN);
3268 on_button3Eraser_activate (GtkMenuItem *menuitem,
3271 process_mapping_activate(menuitem, 2, TOOL_ERASER);
3276 on_button3Highlighter_activate (GtkMenuItem *menuitem,
3279 process_mapping_activate(menuitem, 2, TOOL_HIGHLIGHTER);
3284 on_button3Text_activate (GtkMenuItem *menuitem,
3287 process_mapping_activate(menuitem, 2, TOOL_TEXT);
3292 on_button3SelectRegion_activate (GtkMenuItem *menuitem,
3295 process_mapping_activate(menuitem, 2, TOOL_SELECTREGION);
3300 on_button3SelectRectangle_activate (GtkMenuItem *menuitem,
3303 process_mapping_activate(menuitem, 2, TOOL_SELECTRECT);
3308 on_button3VerticalSpace_activate (GtkMenuItem *menuitem,
3311 process_mapping_activate(menuitem, 2, TOOL_VERTSPACE);
3316 on_button3LinkBrush_activate (GtkMenuItem *menuitem,
3321 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3323 ui.linked_brush[2] = BRUSH_LINKED;
3324 for (i=0;i<NUM_STROKE_TOOLS;i++) update_mapping_linkings(i);
3329 on_button3CopyBrush_activate (GtkMenuItem *menuitem,
3332 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3334 if (ui.toolno[2] >= NUM_STROKE_TOOLS) {
3335 ui.linked_brush[2] = BRUSH_STATIC;
3336 update_mappings_menu_linkings();
3339 ui.linked_brush[2] = BRUSH_COPIED;
3340 g_memmove(&(ui.brushes[2][ui.toolno[2]]), &(ui.brushes[0][ui.toolno[2]]), sizeof(struct Brush));
3343 // the set zoom dialog
3345 GtkWidget *zoom_dialog;
3346 double zoom_percent;
3349 on_viewSetZoom_activate (GtkMenuItem *menuitem,
3353 double test_w, test_h;
3354 GtkSpinButton *spinZoom;
3357 zoom_dialog = create_zoomDialog();
3358 zoom_percent = 100*ui.zoom / DEFAULT_ZOOM;
3359 spinZoom = GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(zoom_dialog), "spinZoom"));
3360 gtk_spin_button_set_increments(spinZoom, ui.zoom_step_increment, 5*ui.zoom_step_increment);
3361 gtk_spin_button_set_value(spinZoom, zoom_percent);
3362 test_w = 100*(GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width/DEFAULT_ZOOM;
3363 test_h = 100*(GTK_WIDGET(canvas))->allocation.height/ui.cur_page->height/DEFAULT_ZOOM;
3364 if (zoom_percent > 99.9 && zoom_percent < 100.1)
3365 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3366 G_OBJECT(zoom_dialog), "radioZoom100")), TRUE);
3367 else if (zoom_percent > test_w-0.1 && zoom_percent < test_w+0.1)
3368 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3369 G_OBJECT(zoom_dialog), "radioZoomWidth")), TRUE);
3370 else if (zoom_percent > test_h-0.1 && zoom_percent < test_h+0.1)
3371 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3372 G_OBJECT(zoom_dialog), "radioZoomHeight")), TRUE);
3373 else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3374 G_OBJECT(zoom_dialog), "radioZoom")), TRUE);
3375 gtk_widget_show(zoom_dialog);
3378 response = gtk_dialog_run(GTK_DIALOG(zoom_dialog));
3379 if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY) {
3380 ui.zoom = DEFAULT_ZOOM*zoom_percent/100;
3381 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
3382 rescale_text_items();
3383 rescale_bg_pixmaps();
3385 } while (response == GTK_RESPONSE_APPLY);
3387 gtk_widget_destroy(zoom_dialog);
3392 on_spinZoom_value_changed (GtkSpinButton *spinbutton,
3397 val = gtk_spin_button_get_value(GTK_SPIN_BUTTON(g_object_get_data(
3398 G_OBJECT(zoom_dialog), "spinZoom")));
3400 if (val<10) val=10.;
3401 if (val>1500) val=1500.;
3402 if (val<zoom_percent-1 || val>zoom_percent+1)
3403 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3404 G_OBJECT(zoom_dialog), "radioZoom")), TRUE);
3410 on_radioZoom_toggled (GtkToggleButton *togglebutton,
3418 on_radioZoom100_toggled (GtkToggleButton *togglebutton,
3421 if (!gtk_toggle_button_get_active(togglebutton)) return;
3422 zoom_percent = 100.;
3423 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3424 G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3429 on_radioZoomWidth_toggled (GtkToggleButton *togglebutton,
3432 if (!gtk_toggle_button_get_active(togglebutton)) return;
3433 zoom_percent = 100*(GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width/DEFAULT_ZOOM;
3434 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3435 G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3440 on_radioZoomHeight_toggled (GtkToggleButton *togglebutton,
3443 if (!gtk_toggle_button_get_active(togglebutton)) return;
3444 zoom_percent = 100*(GTK_WIDGET(canvas))->allocation.height/ui.cur_page->height/DEFAULT_ZOOM;
3445 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3446 G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3451 on_toolsHand_activate (GtkMenuItem *menuitem,
3454 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
3455 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
3458 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
3462 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
3463 if (ui.toolno[ui.cur_mapping] == TOOL_HAND) return;
3468 ui.toolno[ui.cur_mapping] = TOOL_HAND;
3469 update_mapping_linkings(-1);
3470 update_tool_buttons();
3472 update_color_menu();
3478 on_button2Hand_activate (GtkMenuItem *menuitem,
3481 process_mapping_activate(menuitem, 1, TOOL_HAND);
3486 on_button3Hand_activate (GtkMenuItem *menuitem,
3489 process_mapping_activate(menuitem, 2, TOOL_HAND);
3494 on_optionsPrintRuling_activate (GtkMenuItem *menuitem,
3498 ui.print_ruling = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3502 on_optionsAutoloadPdfXoj_activate (GtkMenuItem *menuitem,
3506 ui.autoload_pdf_xoj = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3510 on_fontButton_font_set (GtkFontButton *fontbutton,
3515 str = g_strdup(gtk_font_button_get_font_name(fontbutton));
3516 process_font_sel(str);
3520 on_optionsLeftHanded_activate (GtkMenuItem *menuitem,
3524 ui.left_handed = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3525 gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW(GET_COMPONENT("scrolledwindowMain")),
3526 ui.left_handed?GTK_CORNER_TOP_RIGHT:GTK_CORNER_TOP_LEFT);
3530 on_optionsShortenMenus_activate (GtkMenuItem *menuitem,
3533 gchar *item, *nextptr;
3537 ui.shorten_menus = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3539 /* go over the item list */
3540 item = ui.shorten_menu_items;
3541 while (*item==' ') item++;
3543 nextptr = strchr(item, ' ');
3544 if (nextptr!=NULL) *nextptr = 0;
3545 // hide or show the item
3546 w = GET_COMPONENT(item);
3548 if (ui.shorten_menus) gtk_widget_hide(w);
3549 else gtk_widget_show(w);
3552 if (nextptr==NULL) break;
3555 while (*item==' ') item++;
3558 // just in case someone tried to unhide stuff they shouldn't be seeing
3559 hide_unimplemented();
3560 // maybe we should also make sure the drawing area stays visible ?
3564 on_optionsAutoSavePrefs_activate (GtkMenuItem *menuitem,
3568 ui.auto_save_prefs = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3572 on_optionsPressureSensitive_activate (GtkMenuItem *menuitem,
3577 ui.pressure_sensitivity =
3578 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3579 for (i=0; i<=NUM_BUTTONS; i++)
3580 ui.brushes[i][TOOL_PEN].variable_width = ui.pressure_sensitivity;
3581 update_mappings_menu();
3586 on_buttonColorChooser_set (GtkColorButton *colorbutton,
3592 gtk_color_button_get_color(colorbutton, &gdkcolor);
3593 alpha = gtk_color_button_get_alpha(colorbutton);
3594 process_color_activate((GtkMenuItem*)colorbutton, COLOR_OTHER, gdkcolor_to_rgba(gdkcolor, alpha));
3599 on_optionsButtonsSwitchMappings_activate(GtkMenuItem *menuitem,
3604 ui.button_switch_mapping = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));