X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=src%2Fxo-misc.c;h=410797cd875af6a4ec2a19fbb298a56524389482;hb=dcbb0ab8521a5e166f257d86884407eb98ef63f0;hp=7cfe98410d068ef218476d7fb5eec14090afae5d;hpb=64fbee630efe4a6a731bcc7b68855d933946b050;p=xournal.git diff --git a/src/xo-misc.c b/src/xo-misc.c index 7cfe984..410797c 100644 --- a/src/xo-misc.c +++ b/src/xo-misc.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "xournal.h" #include "xo-interface.h" @@ -14,6 +15,7 @@ #include "xo-misc.h" #include "xo-file.h" #include "xo-paint.h" +#include "xo-shapes.h" // some global constants @@ -94,6 +96,13 @@ void realloc_cur_path(int n) ui.cur_path.coords = g_realloc(ui.cur_path.coords, 2*(n+10)*sizeof(double)); } +void realloc_cur_widths(int n) +{ + if (n <= ui.cur_widths_storage_alloc) return; + ui.cur_widths_storage_alloc = n+10; + ui.cur_widths = g_realloc(ui.cur_widths, (n+10)*sizeof(double)); +} + // undo utility functions void prepare_new_undo(void) @@ -123,15 +132,22 @@ void clear_redo_stack(void) while (redo!=NULL) { if (redo->type == ITEM_STROKE) { gnome_canvas_points_free(redo->item->path); + if (redo->item->brush.variable_width) g_free(redo->item->widths); g_free(redo->item); /* the strokes are unmapped, so there are no associated canvas items */ } - else if (redo->type == ITEM_ERASURE) { + else if (redo->type == ITEM_TEXT) { + g_free(redo->item->text); + g_free(redo->item->font_name); + g_free(redo->item); + } + else if (redo->type == ITEM_ERASURE || redo->type == ITEM_RECOGNIZER) { for (list = redo->erasurelist; list!=NULL; list=list->next) { erasure = (struct UndoErasureData *)list->data; for (repl = erasure->replacement_items; repl!=NULL; repl=repl->next) { it = (struct Item *)repl->data; gnome_canvas_points_free(it->path); + if (it->brush.variable_width) g_free(it->widths); g_free(it); } g_list_free(erasure->replacement_items); @@ -154,10 +170,16 @@ void clear_redo_stack(void) else if (redo->type == ITEM_MOVESEL || redo->type == ITEM_REPAINTSEL) { g_list_free(redo->itemlist); g_list_free(redo->auxlist); } + else if (redo->type == ITEM_RESIZESEL) { + g_list_free(redo->itemlist); + } else if (redo->type == ITEM_PASTE) { for (list = redo->itemlist; list!=NULL; list=list->next) { it = (struct Item *)list->data; - if (it->type == ITEM_STROKE) gnome_canvas_points_free(it->path); + if (it->type == ITEM_STROKE) { + gnome_canvas_points_free(it->path); + if (it->brush.variable_width) g_free(it->widths); + } g_free(it); } g_list_free(redo->itemlist); @@ -165,6 +187,10 @@ void clear_redo_stack(void) else if (redo->type == ITEM_NEW_LAYER) { g_free(redo->layer); } + else if (redo->type == ITEM_TEXT_EDIT || redo->type == ITEM_TEXT_ATTRIB) { + g_free(redo->str); + if (redo->type == ITEM_TEXT_ATTRIB) g_free(redo->brush); + } u = redo; redo = redo->next; @@ -182,10 +208,15 @@ void clear_undo_stack(void) while (undo!=NULL) { // for strokes, items are already in the journal, so we don't free them // for erasures, we need to free the dead items - if (undo->type == ITEM_ERASURE) { + if (undo->type == ITEM_ERASURE || undo->type == ITEM_RECOGNIZER) { for (list = undo->erasurelist; list!=NULL; list=list->next) { erasure = (struct UndoErasureData *)list->data; - gnome_canvas_points_free(erasure->item->path); + if (erasure->item->type == ITEM_STROKE) { + gnome_canvas_points_free(erasure->item->path); + if (erasure->item->brush.variable_width) g_free(erasure->item->widths); + } + if (erasure->item->type == ITEM_TEXT) + { g_free(erasure->item->text); g_free(erasure->item->font_name); } g_free(erasure->item); g_list_free(erasure->replacement_items); g_free(erasure); @@ -203,6 +234,9 @@ void clear_undo_stack(void) else if (undo->type == ITEM_MOVESEL || undo->type == ITEM_REPAINTSEL) { g_list_free(undo->itemlist); g_list_free(undo->auxlist); } + else if (undo->type == ITEM_RESIZESEL) { + g_list_free(undo->itemlist); + } else if (undo->type == ITEM_PASTE) { g_list_free(undo->itemlist); } @@ -214,6 +248,10 @@ void clear_undo_stack(void) undo->page->group = NULL; delete_page(undo->page); } + else if (undo->type == ITEM_TEXT_EDIT || undo->type == ITEM_TEXT_ATTRIB) { + g_free(undo->str); + if (undo->type == ITEM_TEXT_ATTRIB) g_free(undo->brush); + } u = undo; undo = undo->next; @@ -260,6 +298,9 @@ void delete_layer(struct Layer *l) item = (struct Item *)l->items->data; if (item->type == ITEM_STROKE && item->path != NULL) gnome_canvas_points_free(item->path); + if (item->type == ITEM_TEXT) { + g_free(item->font_name); g_free(item->text); + } // don't need to delete the canvas_item, as it's part of the group destroyed below g_free(item); l->items = g_list_delete_link(l->items, l->items); @@ -310,10 +351,11 @@ void get_pointer_coords(GdkEvent *event, gdouble *ret) void fix_xinput_coords(GdkEvent *event) { +#ifdef ENABLE_XINPUT_BUGFIX double *axes, *px, *py, axis_width; GdkDevice *device; int wx, wy, sx, sy; - + if (event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) { axes = event->button.axes; px = &(event->button.x); @@ -328,7 +370,8 @@ void fix_xinput_coords(GdkEvent *event) } else return; // nothing we know how to do - gdk_window_get_origin(event->any.window, &wx, &wy); + // use canvas window, not event window (else get GTK+ 2.11 bugs!) + gdk_window_get_origin(GTK_WIDGET(canvas)->window, &wx, &wy); gnome_canvas_get_scroll_offsets(canvas, &sx, &sy); axis_width = device->axes[0].max - device->axes[0].min; @@ -338,12 +381,25 @@ void fix_xinput_coords(GdkEvent *event) axis_width = device->axes[1].max - device->axes[1].min; if (axis_width>EPSILON) *py = (axes[1]/axis_width)*ui.screen_height + sy - wy; +#endif +} + +double get_pressure_multiplier(GdkEvent *event) +{ + double rawpressure; + + if (event->button.device == gdk_device_get_core_pointer() + || event->button.device->num_axes <= 2) return 1.0; + + rawpressure = event->button.axes[2]/(event->button.device->axes[2].max - event->button.device->axes[2].min); + + return ((1-rawpressure)*ui.width_minimum_multiplier + rawpressure*ui.width_maximum_multiplier); } void update_item_bbox(struct Item *item) { int i; - double *p; + gdouble *p, h, w; if (item->type == ITEM_STROKE) { item->bbox.left = item->bbox.right = item->path->coords[0]; @@ -356,6 +412,12 @@ void update_item_bbox(struct Item *item) if (p[1] > item->bbox.bottom) item->bbox.bottom = p[1]; } } + if (item->type == ITEM_TEXT && item->canvas_item!=NULL) { + h=0.; w=0.; + g_object_get(item->canvas_item, "text_width", &w, "text_height", &h, NULL); + item->bbox.right = item->bbox.left + w; + item->bbox.bottom = item->bbox.top + h; + } } void make_page_clipbox(struct Page *pg) @@ -372,6 +434,47 @@ void make_page_clipbox(struct Page *pg) gnome_canvas_path_def_unref(pg_clip); } +void make_canvas_item_one(GnomeCanvasGroup *group, struct Item *item) +{ + PangoFontDescription *font_desc; + GnomeCanvasPoints points; + int j; + + if (item->type == ITEM_STROKE) { + if (!item->brush.variable_width) + item->canvas_item = gnome_canvas_item_new(group, + gnome_canvas_line_get_type(), "points", item->path, + "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, + "fill-color-rgba", item->brush.color_rgba, + "width-units", item->brush.thickness, NULL); + else { + item->canvas_item = gnome_canvas_item_new(group, + gnome_canvas_group_get_type(), NULL); + points.num_points = 2; + points.ref_count = 1; + for (j = 0; j < item->path->num_points-1; j++) { + points.coords = item->path->coords+2*j; + gnome_canvas_item_new((GnomeCanvasGroup *) item->canvas_item, + gnome_canvas_line_get_type(), "points", &points, + "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, + "fill-color-rgba", item->brush.color_rgba, + "width-units", item->widths[j], NULL); + } + } + } + if (item->type == ITEM_TEXT) { + font_desc = pango_font_description_from_string(item->font_name); + pango_font_description_set_absolute_size(font_desc, + item->font_size*ui.zoom*PANGO_SCALE); + item->canvas_item = gnome_canvas_item_new(group, + gnome_canvas_text_get_type(), + "x", item->bbox.left, "y", item->bbox.top, "anchor", GTK_ANCHOR_NW, + "font-desc", font_desc, "fill-color-rgba", item->brush.color_rgba, + "text", item->text, NULL); + update_item_bbox(item); + } +} + void make_canvas_items(void) { struct Page *pg; @@ -394,13 +497,8 @@ void make_canvas_items(void) pg->group, gnome_canvas_group_get_type(), NULL); for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next) { item = (struct Item *)itemlist->data; - if (item->type == ITEM_STROKE && item->canvas_item == NULL) { - item->canvas_item = gnome_canvas_item_new(l->group, - gnome_canvas_line_get_type(), "points", item->path, - "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, - "fill-color-rgba", item->brush.color_rgba, - "width-units", item->brush.thickness, NULL); - } + if (item->canvas_item == NULL) + make_canvas_item_one(l->group, item); } } } @@ -586,6 +684,14 @@ void lower_canvas_item_to(GnomeCanvasGroup *g, GnomeCanvasItem *item, GnomeCanva g->item_list_end = g_list_last(g->item_list); } +void rgb_to_gdkcolor(guint rgba, GdkColor *color) +{ + color->pixel = 0; + color->red = ((rgba>>24)&0xff)*0x101; + color->green = ((rgba>>16)&0xff)*0x101; + color->blue = ((rgba>>8)&0xff)*0x101; +} + // some interface functions void update_thickness_buttons(void) @@ -616,7 +722,7 @@ void update_thickness_buttons(void) void update_color_buttons(void) { if (ui.selection!=NULL || (ui.toolno[ui.cur_mapping] != TOOL_PEN - && ui.toolno[ui.cur_mapping] != TOOL_HIGHLIGHTER)) { + && ui.toolno[ui.cur_mapping] != TOOL_HIGHLIGHTER && ui.toolno[ui.cur_mapping] != TOOL_TEXT)) { gtk_toggle_tool_button_set_active( GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonColorOther")), TRUE); } else @@ -709,7 +815,12 @@ void update_tool_buttons(void) } gtk_toggle_tool_button_set_active( - GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonRuler")), ui.ruler[ui.cur_mapping]); + GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonRuler")), + ui.toolno[ui.cur_mapping]ruler); + gtk_toggle_tool_button_set_active( + GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonReco")), + ui.toolno[ui.cur_mapping]recognizer); + update_thickness_buttons(); update_color_buttons(); } @@ -752,21 +863,33 @@ void update_tool_menu(void) } gtk_check_menu_item_set_active( - GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsRuler")), ui.ruler[0]); + GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsRuler")), + ui.toolno[0]ruler); + gtk_toggle_tool_button_set_active( + GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonReco")), + ui.toolno[ui.cur_mapping]recognizer); + gtk_check_menu_item_set_active( + GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsRuler")), + ui.toolno[0]voffset*ui.zoom); + ui.cur_page->voffset*ui.zoom); */ + gnome_canvas_get_scroll_offsets(canvas, &cx, &cy); + cy = ui.cur_page->voffset*ui.zoom; + gnome_canvas_scroll_to(canvas, cx, cy); + if (refresh_all) gnome_canvas_set_pixels_per_unit(canvas, ui.zoom); else if (!ui.view_continuous) @@ -1038,8 +1169,6 @@ void update_page_stuff(void) GtkSpinButton *spin; struct Page *pg; double vertpos, maxwidth; - struct Layer *layer; - int relscroll; // move the page groups to their rightful locations or hide them if (ui.view_continuous) { @@ -1232,9 +1361,11 @@ void update_copy_paste_enabled(void) { gtk_widget_set_sensitive(GET_COMPONENT("editCut"), ui.selection!=NULL); gtk_widget_set_sensitive(GET_COMPONENT("editCopy"), ui.selection!=NULL); + gtk_widget_set_sensitive(GET_COMPONENT("editPaste"), ui.cur_item_type!=ITEM_TEXT); gtk_widget_set_sensitive(GET_COMPONENT("editDelete"), ui.selection!=NULL); gtk_widget_set_sensitive(GET_COMPONENT("buttonCut"), ui.selection!=NULL); gtk_widget_set_sensitive(GET_COMPONENT("buttonCopy"), ui.selection!=NULL); + gtk_widget_set_sensitive(GET_COMPONENT("buttonPaste"), ui.cur_item_type!=ITEM_TEXT); } void update_mapping_linkings(int toolno) @@ -1245,9 +1376,6 @@ void update_mapping_linkings(int toolno) if (ui.linked_brush[i] == BRUSH_LINKED) { if (toolno >= 0 && toolno < NUM_STROKE_TOOLS) g_memmove(&(ui.brushes[i][toolno]), &(ui.brushes[0][toolno]), sizeof(struct Brush)); - ui.ruler[i] = ui.ruler[0]; - if (ui.toolno[i]!=TOOL_PEN && ui.toolno[i]!=TOOL_HIGHLIGHTER) - ui.ruler[i] = FALSE; } if (ui.linked_brush[i] == BRUSH_COPIED && toolno == ui.toolno[i]) { ui.linked_brush[i] = BRUSH_STATIC; @@ -1260,12 +1388,32 @@ void set_cur_color(int color) { ui.cur_brush->color_no = color; if (ui.toolno[0] == TOOL_HIGHLIGHTER) - ui.cur_brush->color_rgba = predef_colors_rgba[color] & HILITER_ALPHA_MASK; + ui.cur_brush->color_rgba = predef_colors_rgba[color] & ui.hiliter_alpha_mask; else ui.cur_brush->color_rgba = predef_colors_rgba[color]; update_mapping_linkings(ui.toolno[0]); } +void recolor_temp_text(int color_no, guint color_rgba) +{ + GdkColor gdkcolor; + + if (ui.cur_item_type!=ITEM_TEXT) return; + if (ui.cur_item->text!=NULL && ui.cur_item->brush.color_rgba != color_rgba) { + prepare_new_undo(); + undo->type = ITEM_TEXT_ATTRIB; + undo->item = ui.cur_item; + undo->str = g_strdup(ui.cur_item->font_name); + undo->val_x = ui.cur_item->font_size; + undo->brush = (struct Brush *)g_memdup(&(ui.cur_item->brush), sizeof(struct Brush)); + } + ui.cur_item->brush.color_no = color_no; + ui.cur_item->brush.color_rgba = color_rgba; + rgb_to_gdkcolor(color_rgba, &gdkcolor); + gtk_widget_modify_text(ui.cur_item->widget, GTK_STATE_NORMAL, &gdkcolor); + gtk_widget_grab_focus(ui.cur_item->widget); +} + void process_color_activate(GtkMenuItem *menuitem, int color) { if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) { @@ -1277,6 +1425,10 @@ void process_color_activate(GtkMenuItem *menuitem, int color) } if (ui.cur_mapping != 0) return; // not user-generated + reset_focus(); + + if (ui.cur_item_type == ITEM_TEXT) + recolor_temp_text(color, predef_colors_rgba[color]); if (ui.selection != NULL) { recolor_selection(color); @@ -1284,8 +1436,10 @@ void process_color_activate(GtkMenuItem *menuitem, int color) update_color_menu(); } - if (ui.toolno[0] != TOOL_PEN && ui.toolno[0] != TOOL_HIGHLIGHTER) { + if (ui.toolno[0] != TOOL_PEN && ui.toolno[0] != TOOL_HIGHLIGHTER + && ui.toolno[0] != TOOL_TEXT) { if (ui.selection != NULL) return; + end_text(); ui.toolno[0] = TOOL_PEN; ui.cur_brush = &(ui.brushes[0][TOOL_PEN]); update_tool_buttons(); @@ -1311,6 +1465,7 @@ void process_thickness_activate(GtkMenuItem *menuitem, int tool, int val) if (ui.cur_mapping != 0) return; // not user-generated if (ui.selection != NULL && GTK_OBJECT_TYPE(menuitem) != GTK_TYPE_RADIO_MENU_ITEM) { + reset_focus(); rethicken_selection(val); update_thickness_buttons(); } @@ -1320,6 +1475,9 @@ void process_thickness_activate(GtkMenuItem *menuitem, int tool, int val) return; } + if (ui.brushes[0][tool].thickness_no == val) return; + reset_focus(); + end_text(); ui.brushes[0][tool].thickness_no = val; ui.brushes[0][tool].thickness = predef_thickness[tool][val]; update_mapping_linkings(tool); @@ -1416,7 +1574,6 @@ gboolean ok_to_close(void) { GtkWidget *dialog; GtkResponseType response; - GList *pagelist; if (ui.saved) return TRUE; dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT, @@ -1440,6 +1597,16 @@ gboolean page_ops_forbidden(void) return (bgpdf.status != STATUS_NOT_INIT && bgpdf.create_pages); } +// send the focus back to the appropriate widget +void reset_focus(void) +{ + if (ui.cur_item_type == ITEM_TEXT) + gtk_widget_grab_focus(ui.cur_item->widget); + else + gtk_widget_grab_focus(GTK_WIDGET(canvas)); + reset_recognizer(); +} + // selection / clipboard stuff void reset_selection(void) @@ -1454,6 +1621,7 @@ void reset_selection(void) update_color_menu(); update_thickness_buttons(); update_color_buttons(); + update_font_button(); } void move_journal_items_by(GList *itemlist, double dx, double dy, @@ -1467,9 +1635,10 @@ void move_journal_items_by(GList *itemlist, double dx, double dy, while (itemlist!=NULL) { item = (struct Item *)itemlist->data; - if (item->type == ITEM_STROKE) { + if (item->type == ITEM_STROKE) for (pt=item->path->coords, i=0; ipath->num_points; i++, pt+=2) { pt[0] += dx; pt[1] += dy; } + if (item->type == ITEM_STROKE || item->type == ITEM_TEXT || item->type == ITEM_TEMP_TEXT) { item->bbox.left += dx; item->bbox.right += dx; item->bbox.top += dy; @@ -1503,6 +1672,64 @@ void move_journal_items_by(GList *itemlist, double dx, double dy, } } +void resize_journal_items_by(GList *itemlist, double scaling_x, double scaling_y, + double offset_x, double offset_y) +{ + struct Item *item; + GList *list; + double mean_scaling, temp; + double *pt, *wid; + GnomeCanvasGroup *group; + int i; + + /* geometric mean of x and y scalings = rescaling for stroke widths + and for text font sizes */ + mean_scaling = sqrt(fabs(scaling_x * scaling_y)); + + for (list = itemlist; list != NULL; list = list->next) { + item = (struct Item *)list->data; + if (item->type == ITEM_STROKE) { + item->brush.thickness = item->brush.thickness * mean_scaling; + for (i=0, pt=item->path->coords; ipath->num_points; i++, pt+=2) { + pt[0] = pt[0]*scaling_x + offset_x; + pt[1] = pt[1]*scaling_y + offset_y; + } + if (item->brush.variable_width) + for (i=0, wid=item->widths; ipath->num_points-1; i++, wid++) + *wid = *wid * mean_scaling; + + item->bbox.left = item->bbox.left*scaling_x + offset_x; + item->bbox.right = item->bbox.right*scaling_x + offset_x; + item->bbox.top = item->bbox.top*scaling_y + offset_y; + item->bbox.bottom = item->bbox.bottom*scaling_y + offset_y; + if (item->bbox.left > item->bbox.right) { + temp = item->bbox.left; + item->bbox.left = item->bbox.right; + item->bbox.right = temp; + } + if (item->bbox.top > item->bbox.bottom) { + temp = item->bbox.top; + item->bbox.top = item->bbox.bottom; + item->bbox.bottom = temp; + } + } + if (item->type == ITEM_TEXT) { + /* must scale about NW corner -- all other points of the text box + are font- and zoom-dependent, so scaling about center of text box + couldn't be undone properly. FIXME? */ + item->font_size *= mean_scaling; + item->bbox.left = item->bbox.left*scaling_x + offset_x; + item->bbox.top = item->bbox.top*scaling_y + offset_y; + } + // redraw the item + if (item->canvas_item!=NULL) { + group = (GnomeCanvasGroup *) item->canvas_item->parent; + gtk_object_destroy(GTK_OBJECT(item->canvas_item)); + make_canvas_item_one(group, item); + } + } +} + // Switch between button mappings /* NOTE ABOUT BUTTON MAPPINGS: ui.cur_mapping is 0 except while a canvas @@ -1515,6 +1742,8 @@ void switch_mapping(int m) ui.cur_mapping = m; if (ui.toolno[m] < NUM_STROKE_TOOLS) ui.cur_brush = &(ui.brushes[m][ui.toolno[m]]); + if (ui.toolno[m] == TOOL_TEXT) + ui.cur_brush = &(ui.brushes[m][TOOL_PEN]); update_tool_buttons(); update_color_menu(); update_cursor(); @@ -1525,11 +1754,10 @@ void process_mapping_activate(GtkMenuItem *menuitem, int m, int tool) if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return; if (ui.cur_mapping!=0) return; if (ui.toolno[m] == tool) return; + end_text(); + reset_focus(); + ui.toolno[m] = tool; - ui.ruler[m] = FALSE; - if (ui.linked_brush[m] == BRUSH_LINKED - && (tool==TOOL_PEN || tool==TOOL_HIGHLIGHTER)) - ui.ruler[m] = ui.ruler[0]; if (ui.linked_brush[m] == BRUSH_COPIED) { ui.linked_brush[m] = BRUSH_STATIC; update_mappings_menu_linkings(); @@ -1561,3 +1789,160 @@ void update_vbox_order(int *order) if (!present[i]) gtk_widget_hide(GET_COMPONENT(vbox_component_names[i])); } +gchar *make_cur_font_name(void) +{ + gchar *str; + struct Item *it; + + if (ui.cur_item_type == ITEM_TEXT) + str = g_strdup_printf("%s %.1f", ui.cur_item->font_name, ui.cur_item->font_size); + else if (ui.selection!=NULL && ui.selection->items!=NULL && + ui.selection->items->next==NULL && + (it=(struct Item*)ui.selection->items->data)->type == ITEM_TEXT) + str = g_strdup_printf("%s %.1f", it->font_name, it->font_size); + else + str = g_strdup_printf("%s %.1f", ui.font_name, ui.font_size); + return str; +} + +void update_font_button(void) +{ + gchar *str; + + str = make_cur_font_name(); + gtk_font_button_set_font_name(GTK_FONT_BUTTON(GET_COMPONENT("fontButton")), str); + g_free(str); +} + +gboolean can_accel(GtkWidget *widget, guint id, gpointer data) +{ + return GTK_WIDGET_SENSITIVE(widget); +} + +void allow_all_accels(void) +{ + g_signal_connect((gpointer) GET_COMPONENT("fileNew"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("fileOpen"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("fileSave"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("filePrint"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("filePrintPDF"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("fileQuit"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("editUndo"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("editRedo"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("editCut"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("editCopy"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("editPaste"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("editDelete"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewFullscreen"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewZoomIn"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewZoomOut"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewNormalSize"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewPageWidth"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewFirstPage"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewPreviousPage"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewNextPage"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewLastPage"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("toolsPen"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("toolsEraser"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("toolsHighlighter"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("toolsText"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); +/* g_signal_connect((gpointer) GET_COMPONENT("toolsSelectRegion"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); */ + g_signal_connect((gpointer) GET_COMPONENT("toolsSelectRectangle"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("toolsVerticalSpace"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("toolsHand"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("toolsTextFont"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("toolsRuler"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); +} + +void add_scroll_bindings(void) +{ + GtkBindingSet *binding_set; + + binding_set = gtk_binding_set_by_class( + G_OBJECT_GET_CLASS(GET_COMPONENT("scrolledwindowMain"))); + gtk_binding_entry_add_signal(binding_set, GDK_Up, 0, + "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_BACKWARD, + G_TYPE_BOOLEAN, FALSE); + gtk_binding_entry_add_signal(binding_set, GDK_KP_Up, 0, + "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_BACKWARD, + G_TYPE_BOOLEAN, FALSE); + gtk_binding_entry_add_signal(binding_set, GDK_Down, 0, + "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_FORWARD, + G_TYPE_BOOLEAN, FALSE); + gtk_binding_entry_add_signal(binding_set, GDK_KP_Down, 0, + "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_FORWARD, + G_TYPE_BOOLEAN, FALSE); + gtk_binding_entry_add_signal(binding_set, GDK_Left, 0, + "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_BACKWARD, + G_TYPE_BOOLEAN, TRUE); + gtk_binding_entry_add_signal(binding_set, GDK_KP_Left, 0, + "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_BACKWARD, + G_TYPE_BOOLEAN, TRUE); + gtk_binding_entry_add_signal(binding_set, GDK_Right, 0, + "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_FORWARD, + G_TYPE_BOOLEAN, TRUE); + gtk_binding_entry_add_signal(binding_set, GDK_KP_Right, 0, + "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_FORWARD, + G_TYPE_BOOLEAN, TRUE); +} + +gboolean is_event_within_textview(GdkEventButton *event) +{ + double pt[2]; + + if (ui.cur_item_type!=ITEM_TEXT) return FALSE; + get_pointer_coords((GdkEvent *)event, pt); + if (pt[0]bbox.left || pt[0]>ui.cur_item->bbox.right) return FALSE; + if (pt[1]bbox.top || pt[1]>ui.cur_item->bbox.bottom) return FALSE; + return TRUE; +} + +void hide_unimplemented(void) +{ + gtk_widget_hide(GET_COMPONENT("filePrintOptions")); + gtk_widget_hide(GET_COMPONENT("journalFlatten")); + gtk_widget_hide(GET_COMPONENT("papercolorOther")); + gtk_widget_hide(GET_COMPONENT("toolsSelectRegion")); + gtk_widget_hide(GET_COMPONENT("buttonSelectRegion")); + gtk_widget_hide(GET_COMPONENT("button2SelectRegion")); + gtk_widget_hide(GET_COMPONENT("button3SelectRegion")); + gtk_widget_hide(GET_COMPONENT("colorOther")); + gtk_widget_hide(GET_COMPONENT("helpIndex")); + + /* config file only works with glib 2.6 */ + if (glib_minor_version<6) { + gtk_widget_hide(GET_COMPONENT("optionsAutoSavePrefs")); + gtk_widget_hide(GET_COMPONENT("optionsSavePreferences")); + } +}