7 #include <libgnomecanvas/libgnomecanvas.h>
10 #include "xo-interface.h"
11 #include "xo-support.h"
12 #include "xo-callbacks.h"
15 // some global constants
17 guint predef_colors_rgba[COLOR_MAX] =
18 { 0x000000ff, 0x3333ccff, 0xff0000ff, 0x008000ff,
19 0x808080ff, 0x00c0ffff, 0x00ff00ff, 0xff00ffff,
20 0xff8000ff, 0xffff00ff, 0xffffffff };
22 guint predef_bgcolors_rgba[COLOR_MAX] = // meaningless ones set to white
23 { 0xffffffff, 0xa0e8ffff, 0xffc0d4ff, 0x80ffc0ff,
24 0xffffffff, 0xa0e8ffff, 0x80ffc0ff, 0xffc0d4ff,
25 0xffc080ff, 0xffff80ff, 0xffffffff };
27 double predef_thickness[NUM_STROKE_TOOLS][THICKNESS_MAX] =
28 { { 0.42, 0.85, 1.41, 2.26, 5.67 }, // pen thicknesses = 0.15, 0.3, 0.5, 0.8, 2 mm
29 { 2.83, 2.83, 7.08, 14.17, 14.17 }, // eraser thicknesses = 1, 2.5, 5 mm
30 { 2.83, 2.83, 7.08, 14.17, 14.17 }, // highlighter thicknesses = 1, 2.5, 5 mm
33 // some manipulation functions
35 struct Page *new_page(struct Page *template)
37 struct Page *pg = (struct Page *) g_memdup(template, sizeof(struct Page));
38 struct Layer *l = g_new(struct Layer, 1);
42 pg->layers = g_list_append(NULL, l);
44 pg->bg = (struct Background *)g_memdup(template->bg, sizeof(struct Background));
45 pg->bg->canvas_item = NULL;
46 if (pg->bg->type == BG_PIXMAP || pg->bg->type == BG_PDF) {
47 gdk_pixbuf_ref(pg->bg->pixbuf);
48 refstring_ref(pg->bg->filename);
50 pg->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
51 gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
52 make_page_clipbox(pg);
54 l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
55 pg->group, gnome_canvas_group_get_type(), NULL);
60 /* Create a page from a background.
61 Note: bg should be an UNREFERENCED background.
62 If needed, first duplicate it and increase the refcount of the pixbuf.
64 struct Page *new_page_with_bg(struct Background *bg, double width, double height)
66 struct Page *pg = g_new(struct Page, 1);
67 struct Layer *l = g_new(struct Layer, 1);
71 pg->layers = g_list_append(NULL, l);
74 pg->bg->canvas_item = NULL;
77 pg->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
78 gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
79 make_page_clipbox(pg);
81 l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
82 pg->group, gnome_canvas_group_get_type(), NULL);
87 void realloc_cur_path(int n)
89 if (n <= ui.cur_path_storage_alloc) return;
90 ui.cur_path_storage_alloc = n+10;
91 ui.cur_path.coords = g_realloc(ui.cur_path.coords, 2*(n+10)*sizeof(double));
94 // undo utility functions
96 void prepare_new_undo(void)
99 // add a new UndoItem on the stack
100 u = (struct UndoItem *)g_malloc(sizeof(struct UndoItem));
108 void clear_redo_stack(void)
112 struct UndoErasureData *erasure;
115 /* Warning: the redo items might reference items from past redo entries,
116 which have been destroyed before them. Be careful! As a rule, it's
117 safe to destroy data which has been created at the current history step,
118 it's unsafe to refer to any data from previous history steps */
121 if (redo->type == ITEM_STROKE) {
122 gnome_canvas_points_free(redo->item->path);
124 /* the strokes are unmapped, so there are no associated canvas items */
126 else if (redo->type == ITEM_ERASURE) {
127 for (list = redo->erasurelist; list!=NULL; list=list->next) {
128 erasure = (struct UndoErasureData *)list->data;
129 for (repl = erasure->replacement_items; repl!=NULL; repl=repl->next) {
130 it = (struct Item *)repl->data;
131 gnome_canvas_points_free(it->path);
134 g_list_free(erasure->replacement_items);
137 g_list_free(redo->erasurelist);
139 else if (redo->type == ITEM_NEW_BG_ONE || redo->type == ITEM_NEW_BG_RESIZE
140 || redo->type == ITEM_NEW_DEFAULT_BG) {
141 if (redo->bg->type == BG_PIXMAP || redo->bg->type == BG_PDF) {
142 if (redo->bg->pixbuf!=NULL) gdk_pixbuf_unref(redo->bg->pixbuf);
143 refstring_unref(redo->bg->filename);
147 else if (redo->type == ITEM_NEW_PAGE) {
148 redo->page->group = NULL;
149 delete_page(redo->page);
151 else if (redo->type == ITEM_MOVESEL) {
152 g_list_free(redo->itemlist);
154 else if (redo->type == ITEM_PASTE) {
155 for (list = redo->itemlist; list!=NULL; list=list->next) {
156 it = (struct Item *)list->data;
157 if (it->type == ITEM_STROKE) gnome_canvas_points_free(it->path);
160 g_list_free(redo->itemlist);
162 else if (redo->type == ITEM_NEW_LAYER) {
170 update_undo_redo_enabled();
173 void clear_undo_stack(void)
177 struct UndoErasureData *erasure;
180 // for strokes, items are already in the journal, so we don't free them
181 // for erasures, we need to free the dead items
182 if (undo->type == ITEM_ERASURE) {
183 for (list = undo->erasurelist; list!=NULL; list=list->next) {
184 erasure = (struct UndoErasureData *)list->data;
185 gnome_canvas_points_free(erasure->item->path);
186 g_free(erasure->item);
187 g_list_free(erasure->replacement_items);
190 g_list_free(undo->erasurelist);
192 else if (undo->type == ITEM_NEW_BG_ONE || undo->type == ITEM_NEW_BG_RESIZE
193 || undo->type == ITEM_NEW_DEFAULT_BG) {
194 if (undo->bg->type == BG_PIXMAP || undo->bg->type == BG_PDF) {
195 if (undo->bg->pixbuf!=NULL) gdk_pixbuf_unref(undo->bg->pixbuf);
196 refstring_unref(undo->bg->filename);
200 else if (undo->type == ITEM_MOVESEL || undo->type == ITEM_PASTE) {
201 g_list_free(undo->itemlist);
203 else if (undo->type == ITEM_DELETE_LAYER) {
204 undo->layer->group = NULL;
205 delete_layer(undo->layer);
207 else if (undo->type == ITEM_DELETE_PAGE) {
208 undo->page->group = NULL;
209 delete_page(undo->page);
216 update_undo_redo_enabled();
219 // free data structures
221 void delete_journal(struct Journal *j)
223 while (j->pages!=NULL) {
224 delete_page((struct Page *)j->pages->data);
225 j->pages = g_list_delete_link(j->pages, j->pages);
229 void delete_page(struct Page *pg)
233 while (pg->layers!=NULL) {
234 l = (struct Layer *)pg->layers->data;
237 pg->layers = g_list_delete_link(pg->layers, pg->layers);
239 if (pg->group!=NULL) gtk_object_destroy(GTK_OBJECT(pg->group));
240 // this also destroys the background's canvas items
241 if (pg->bg->type == BG_PIXMAP || pg->bg->type == BG_PDF) {
242 if (pg->bg->pixbuf != NULL) gdk_pixbuf_unref(pg->bg->pixbuf);
243 if (pg->bg->filename != NULL) refstring_unref(pg->bg->filename);
249 void delete_layer(struct Layer *l)
253 while (l->items!=NULL) {
254 item = (struct Item *)l->items->data;
255 if (item->type == ITEM_STROKE && item->path != NULL)
256 gnome_canvas_points_free(item->path);
257 // don't need to delete the canvas_item, as it's part of the group destroyed below
259 l->items = g_list_delete_link(l->items, l->items);
261 if (l->group!= NULL) gtk_object_destroy(GTK_OBJECT(l->group));
265 // referenced strings
267 struct Refstring *new_refstring(const char *s)
269 struct Refstring *rs = g_new(struct Refstring, 1);
271 if (s!=NULL) rs->s = g_strdup(s);
277 struct Refstring *refstring_ref(struct Refstring *rs)
283 void refstring_unref(struct Refstring *rs)
287 if (rs->s!=NULL) g_free(rs->s);
288 if (rs->aux!=NULL) g_free(rs->aux);
294 // some helper functions
296 void get_pointer_coords(GdkEvent *event, gdouble *ret)
299 gdk_event_get_coords(event, &x, &y);
300 gnome_canvas_window_to_world(canvas, x, y, ret, ret+1);
301 ret[0] -= ui.cur_page->hoffset;
302 ret[1] -= ui.cur_page->voffset;
305 void fix_xinput_coords(GdkEvent *event)
307 double *axes, *px, *py, axis_width;
311 if (event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) {
312 axes = event->button.axes;
313 px = &(event->button.x);
314 py = &(event->button.y);
315 device = event->button.device;
317 else if (event->type == GDK_MOTION_NOTIFY) {
318 axes = event->motion.axes;
319 px = &(event->motion.x);
320 py = &(event->motion.y);
321 device = event->motion.device;
323 else return; // nothing we know how to do
325 gdk_window_get_origin(event->any.window, &wx, &wy);
326 gnome_canvas_get_scroll_offsets(canvas, &sx, &sy);
328 axis_width = device->axes[0].max - device->axes[0].min;
329 if (axis_width>EPSILON)
330 *px = (axes[0]/axis_width)*ui.screen_width + sx - wx;
332 axis_width = device->axes[1].max - device->axes[1].min;
333 if (axis_width>EPSILON)
334 *py = (axes[1]/axis_width)*ui.screen_height + sy - wy;
337 void update_item_bbox(struct Item *item)
342 if (item->type == ITEM_STROKE) {
343 item->bbox.left = item->bbox.right = item->path->coords[0];
344 item->bbox.top = item->bbox.bottom = item->path->coords[1];
345 for (i=1, p=item->path->coords+2; i<item->path->num_points; i++, p+=2)
347 if (p[0] < item->bbox.left) item->bbox.left = p[0];
348 if (p[0] > item->bbox.right) item->bbox.right = p[0];
349 if (p[1] < item->bbox.top) item->bbox.top = p[1];
350 if (p[1] > item->bbox.bottom) item->bbox.bottom = p[1];
355 void make_page_clipbox(struct Page *pg)
357 GnomeCanvasPathDef *pg_clip;
359 pg_clip = gnome_canvas_path_def_new_sized(4);
360 gnome_canvas_path_def_moveto(pg_clip, 0., 0.);
361 gnome_canvas_path_def_lineto(pg_clip, 0., pg->height);
362 gnome_canvas_path_def_lineto(pg_clip, pg->width, pg->height);
363 gnome_canvas_path_def_lineto(pg_clip, pg->width, 0.);
364 gnome_canvas_path_def_closepath(pg_clip);
365 gnome_canvas_item_set(GNOME_CANVAS_ITEM(pg->group), "path", pg_clip, NULL);
366 gnome_canvas_path_def_unref(pg_clip);
369 void make_canvas_items(void)
374 GList *pagelist, *layerlist, *itemlist;
376 for (pagelist = journal.pages; pagelist!=NULL; pagelist = pagelist->next) {
377 pg = (struct Page *)pagelist->data;
378 if (pg->group == NULL) {
379 pg->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
380 gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
381 make_page_clipbox(pg);
383 if (pg->bg->canvas_item == NULL) update_canvas_bg(pg);
384 for (layerlist = pg->layers; layerlist!=NULL; layerlist = layerlist->next) {
385 l = (struct Layer *)layerlist->data;
386 if (l->group == NULL)
387 l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
388 pg->group, gnome_canvas_group_get_type(), NULL);
389 for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next) {
390 item = (struct Item *)itemlist->data;
391 if (item->type == ITEM_STROKE && item->canvas_item == NULL) {
392 item->canvas_item = gnome_canvas_item_new(l->group,
393 gnome_canvas_line_get_type(), "points", item->path,
394 "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND,
395 "fill-color-rgba", item->brush.color_rgba,
396 "width-units", item->brush.thickness, NULL);
403 void update_canvas_bg(struct Page *pg)
405 GnomeCanvasGroup *group;
406 GnomeCanvasPoints *seg;
407 GdkPixbuf *scaled_pix;
412 if (pg->bg->canvas_item != NULL)
413 gtk_object_destroy(GTK_OBJECT(pg->bg->canvas_item));
414 pg->bg->canvas_item = NULL;
416 if (pg->bg->type == BG_SOLID)
418 pg->bg->canvas_item = gnome_canvas_item_new(pg->group,
419 gnome_canvas_group_get_type(), NULL);
420 group = GNOME_CANVAS_GROUP(pg->bg->canvas_item);
421 lower_canvas_item_to(pg->group, pg->bg->canvas_item, NULL);
422 gnome_canvas_item_new(group, gnome_canvas_rect_get_type(),
423 "x1", 0., "x2", pg->width, "y1", 0., "y2", pg->height,
424 "fill-color-rgba", pg->bg->color_rgba, NULL);
425 if (pg->bg->ruling == RULING_NONE) return;
426 seg = gnome_canvas_points_new(2);
428 if (pg->bg->ruling == RULING_GRAPH) {
429 pt[1] = 0; pt[3] = pg->height;
430 for (x=RULING_GRAPHSPACING; x<pg->width-1; x+=RULING_GRAPHSPACING) {
432 gnome_canvas_item_new(group, gnome_canvas_line_get_type(),
433 "points", seg, "fill-color-rgba", RULING_COLOR,
434 "width-units", RULING_THICKNESS, NULL);
436 pt[0] = 0; pt[2] = pg->width;
437 for (y=RULING_GRAPHSPACING; y<pg->height-1; y+=RULING_GRAPHSPACING) {
439 gnome_canvas_item_new(group, gnome_canvas_line_get_type(),
440 "points", seg, "fill-color-rgba", RULING_COLOR,
441 "width-units", RULING_THICKNESS, NULL);
443 gnome_canvas_points_free(seg);
446 pt[0] = 0; pt[2] = pg->width;
447 for (y=RULING_TOPMARGIN; y<pg->height-1; y+=RULING_SPACING) {
449 gnome_canvas_item_new(group, gnome_canvas_line_get_type(),
450 "points", seg, "fill-color-rgba", RULING_COLOR,
451 "width-units", RULING_THICKNESS, NULL);
453 if (pg->bg->ruling == RULING_LINED) {
454 pt[0] = pt[2] = RULING_LEFTMARGIN;
455 pt[1] = 0; pt[3] = pg->height;
456 gnome_canvas_item_new(group, gnome_canvas_line_get_type(),
457 "points", seg, "fill-color-rgba", RULING_MARGIN_COLOR,
458 "width-units", RULING_THICKNESS, NULL);
460 gnome_canvas_points_free(seg);
464 if (pg->bg->type == BG_PIXMAP)
466 if (ui.antialias_bg) {
467 set_cursor_busy(TRUE);
468 w = (int)floor(pg->width*ui.zoom+0.5);
469 h = (int)floor(pg->height*ui.zoom+0.5);
470 if (w == gdk_pixbuf_get_width(pg->bg->pixbuf) &&
471 h == gdk_pixbuf_get_height(pg->bg->pixbuf))
472 scaled_pix = gdk_pixbuf_ref(pg->bg->pixbuf);
474 scaled_pix = gdk_pixbuf_scale_simple(pg->bg->pixbuf, w, h, GDK_INTERP_BILINEAR);
475 pg->bg->pixbuf_scale = ui.zoom;
476 set_cursor_busy(FALSE);
479 scaled_pix = gdk_pixbuf_ref(pg->bg->pixbuf);
480 pg->bg->pixbuf_scale = 0;
482 pg->bg->canvas_item = gnome_canvas_item_new(pg->group,
483 gnome_canvas_pixbuf_get_type(),
484 "pixbuf", scaled_pix,
485 "width", pg->width, "height", pg->height,
486 "width-set", TRUE, "height-set", TRUE,
488 gdk_pixbuf_unref(scaled_pix);
489 lower_canvas_item_to(pg->group, pg->bg->canvas_item, NULL);
492 if (pg->bg->type == BG_PDF)
494 if (pg->bg->pixbuf == NULL) return;
495 pg->bg->canvas_item = gnome_canvas_item_new(pg->group,
496 gnome_canvas_pixbuf_get_type(),
497 "pixbuf", pg->bg->pixbuf,
498 "width", pg->width, "height", pg->height,
499 "width-set", TRUE, "height-set", TRUE,
501 lower_canvas_item_to(pg->group, pg->bg->canvas_item, NULL);
506 gboolean is_visible(struct Page *pg)
508 GtkAdjustment *v_adj;
511 if (!ui.view_continuous) return (pg == ui.cur_page);
512 v_adj = gtk_layout_get_vadjustment(GTK_LAYOUT(canvas));
513 ytop = v_adj->value/ui.zoom;
514 ybot = (v_adj->value + v_adj->page_size) / ui.zoom;
515 return (MAX(ytop, pg->voffset) < MIN(ybot, pg->voffset+pg->height));
518 void rescale_bg_pixmaps(void)
524 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
525 pg = (struct Page *)pglist->data;
526 // in progressive mode we scale only visible pages
527 if (ui.progressive_bg && !is_visible(pg)) continue;
529 if (pg->bg->type == BG_PIXMAP) { // do the rescaling ourselves
530 if (ui.antialias_bg) {
531 if (pg->bg->pixbuf_scale == ui.zoom) continue;
532 set_cursor_busy(TRUE);
533 pix = gdk_pixbuf_scale_simple(pg->bg->pixbuf,
534 (int)floor(pg->width*ui.zoom+0.5), (int)floor(pg->height*ui.zoom+0.5),
535 GDK_INTERP_BILINEAR);
536 gnome_canvas_item_set(pg->bg->canvas_item, "pixbuf", pix, NULL);
537 gdk_pixbuf_unref(pix);
538 pg->bg->pixbuf_scale = ui.zoom;
539 set_cursor_busy(FALSE);
542 pix = GDK_PIXBUF(g_object_get_data(G_OBJECT(pg->bg->canvas_item), "pixbuf"));
543 if (pix!=pg->bg->pixbuf)
544 gnome_canvas_item_set(pg->bg->canvas_item, "pixbuf", pg->bg->pixbuf, NULL);
545 pg->bg->pixbuf_scale = 0;
548 if (pg->bg->type == BG_PDF) { // request an asynchronous update
549 if (pg->bg->pixbuf_scale == ui.zoom) continue;
550 add_bgpdf_request(pg->bg->file_page_seq, ui.zoom, FALSE);
551 pg->bg->pixbuf_scale = ui.zoom;
556 gboolean have_intersect(struct BBox *a, struct BBox *b)
558 return (MAX(a->top, b->top) <= MIN(a->bottom, b->bottom)) &&
559 (MAX(a->left, b->left) <= MIN(a->right, b->right));
562 /* In libgnomecanvas 2.10.0, the lower/raise functions fail to update
563 correctly the end of the group's item list. We try to work around this.
564 DON'T USE gnome_canvas_item_raise/lower directly !! */
566 void lower_canvas_item_to(GnomeCanvasGroup *g, GnomeCanvasItem *item, GnomeCanvasItem *after)
570 i1 = g_list_index(g->item_list, item);
571 if (i1 == -1) return;
573 if (after == NULL) i2 = -1;
574 else i2 = g_list_index(g->item_list, after);
576 if (i1 < i2) gnome_canvas_item_raise(item, i2-i1);
577 if (i1 > i2+1) gnome_canvas_item_lower(item, i1-i2-1);
579 // BUGFIX for libgnomecanvas
580 g->item_list_end = g_list_last(g->item_list);
583 // some interface functions
585 void update_thickness_buttons(void)
587 if (ui.toolno >= NUM_STROKE_TOOLS) {
588 gtk_toggle_tool_button_set_active(
589 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonThicknessOther")), TRUE);
591 switch (ui.cur_brush->thickness_no) {
593 gtk_toggle_tool_button_set_active(
594 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonFine")), TRUE);
596 case THICKNESS_MEDIUM:
597 gtk_toggle_tool_button_set_active(
598 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonMedium")), TRUE);
600 case THICKNESS_THICK:
601 gtk_toggle_tool_button_set_active(
602 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonThick")), TRUE);
605 gtk_toggle_tool_button_set_active(
606 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonThicknessOther")), TRUE);
610 void update_color_buttons(void)
612 if (ui.toolno != TOOL_PEN && ui.toolno != TOOL_HIGHLIGHTER) {
613 gtk_toggle_tool_button_set_active(
614 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonColorOther")), TRUE);
616 switch (ui.cur_brush->color_no) {
618 gtk_toggle_tool_button_set_active(
619 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonBlack")), TRUE);
622 gtk_toggle_tool_button_set_active(
623 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonBlue")), TRUE);
626 gtk_toggle_tool_button_set_active(
627 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonRed")), TRUE);
630 gtk_toggle_tool_button_set_active(
631 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonGreen")), TRUE);
634 gtk_toggle_tool_button_set_active(
635 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonGray")), TRUE);
637 case COLOR_LIGHTBLUE:
638 gtk_toggle_tool_button_set_active(
639 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonLightBlue")), TRUE);
641 case COLOR_LIGHTGREEN:
642 gtk_toggle_tool_button_set_active(
643 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonLightGreen")), TRUE);
646 gtk_toggle_tool_button_set_active(
647 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonMagenta")), TRUE);
650 gtk_toggle_tool_button_set_active(
651 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonOrange")), TRUE);
654 gtk_toggle_tool_button_set_active(
655 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonYellow")), TRUE);
658 gtk_toggle_tool_button_set_active(
659 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonWhite")), TRUE);
662 gtk_toggle_tool_button_set_active(
663 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonColorOther")), TRUE);
667 void update_tool_buttons(void)
671 gtk_toggle_tool_button_set_active(
672 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonPen")), TRUE);
675 gtk_toggle_tool_button_set_active(
676 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonEraser")), TRUE);
678 case TOOL_HIGHLIGHTER:
679 gtk_toggle_tool_button_set_active(
680 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonHighlighter")), TRUE);
683 gtk_toggle_tool_button_set_active(
684 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonText")), TRUE);
686 case TOOL_SELECTREGION:
687 gtk_toggle_tool_button_set_active(
688 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonSelectRegion")), TRUE);
690 case TOOL_SELECTRECT:
691 gtk_toggle_tool_button_set_active(
692 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonSelectRectangle")), TRUE);
695 gtk_toggle_tool_button_set_active(
696 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonVerticalSpace")), TRUE);
700 gtk_toggle_tool_button_set_active(
701 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonRuler")), ui.ruler);
702 update_thickness_buttons();
703 update_color_buttons();
706 void update_tool_menu(void)
710 gtk_check_menu_item_set_active(
711 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsPen")), TRUE);
714 gtk_check_menu_item_set_active(
715 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsEraser")), TRUE);
717 case TOOL_HIGHLIGHTER:
718 gtk_check_menu_item_set_active(
719 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsHighlighter")), TRUE);
722 gtk_check_menu_item_set_active(
723 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsText")), TRUE);
725 case TOOL_SELECTREGION:
726 gtk_check_menu_item_set_active(
727 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsSelectRegion")), TRUE);
729 case TOOL_SELECTRECT:
730 gtk_check_menu_item_set_active(
731 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsSelectRectangle")), TRUE);
734 gtk_check_menu_item_set_active(
735 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsVerticalSpace")), TRUE);
739 gtk_check_menu_item_set_active(
740 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsRuler")), ui.ruler);
743 void update_ruler_indicator(void)
745 gtk_toggle_tool_button_set_active(
746 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonRuler")), ui.ruler);
747 gtk_check_menu_item_set_active(
748 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsRuler")), ui.ruler);
751 void update_color_menu(void)
753 if (ui.toolno != TOOL_PEN && ui.toolno != TOOL_HIGHLIGHTER) {
754 gtk_check_menu_item_set_active(
755 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorNA")), TRUE);
757 switch (ui.cur_brush->color_no) {
759 gtk_check_menu_item_set_active(
760 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorBlack")), TRUE);
763 gtk_check_menu_item_set_active(
764 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorBlue")), TRUE);
767 gtk_check_menu_item_set_active(
768 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorRed")), TRUE);
771 gtk_check_menu_item_set_active(
772 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorGreen")), TRUE);
775 gtk_check_menu_item_set_active(
776 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorGray")), TRUE);
778 case COLOR_LIGHTBLUE:
779 gtk_check_menu_item_set_active(
780 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorLightBlue")), TRUE);
782 case COLOR_LIGHTGREEN:
783 gtk_check_menu_item_set_active(
784 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorLightGreen")), TRUE);
787 gtk_check_menu_item_set_active(
788 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorMagenta")), TRUE);
791 gtk_check_menu_item_set_active(
792 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorOrange")), TRUE);
795 gtk_check_menu_item_set_active(
796 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorYellow")), TRUE);
799 gtk_check_menu_item_set_active(
800 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorWhite")), TRUE);
803 gtk_check_menu_item_set_active(
804 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorOther")), TRUE);
808 void update_pen_props_menu(void)
810 switch(ui.brushes[TOOL_PEN].thickness_no) {
811 case THICKNESS_VERYFINE:
812 gtk_check_menu_item_set_active(
813 GTK_CHECK_MENU_ITEM(GET_COMPONENT("penthicknessVeryFine")), TRUE);
816 gtk_check_menu_item_set_active(
817 GTK_CHECK_MENU_ITEM(GET_COMPONENT("penthicknessFine")), TRUE);
819 case THICKNESS_MEDIUM:
820 gtk_check_menu_item_set_active(
821 GTK_CHECK_MENU_ITEM(GET_COMPONENT("penthicknessMedium")), TRUE);
823 case THICKNESS_THICK:
824 gtk_check_menu_item_set_active(
825 GTK_CHECK_MENU_ITEM(GET_COMPONENT("penthicknessThick")), TRUE);
827 case THICKNESS_VERYTHICK:
828 gtk_check_menu_item_set_active(
829 GTK_CHECK_MENU_ITEM(GET_COMPONENT("penthicknessVeryThick")), TRUE);
834 void update_eraser_props_menu(void)
836 switch (ui.brushes[TOOL_ERASER].thickness_no) {
838 gtk_check_menu_item_set_active(
839 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserFine")), TRUE);
841 case THICKNESS_MEDIUM:
842 gtk_check_menu_item_set_active(
843 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserMedium")), TRUE);
845 case THICKNESS_THICK:
846 gtk_check_menu_item_set_active(
847 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserThick")), TRUE);
851 gtk_check_menu_item_set_active(
852 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserStandard")),
853 ui.brushes[TOOL_ERASER].tool_options == TOOLOPT_ERASER_STANDARD);
854 gtk_check_menu_item_set_active(
855 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserWhiteout")),
856 ui.brushes[TOOL_ERASER].tool_options == TOOLOPT_ERASER_WHITEOUT);
857 gtk_check_menu_item_set_active(
858 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserDeleteStrokes")),
859 ui.brushes[TOOL_ERASER].tool_options == TOOLOPT_ERASER_STROKES);
862 void update_highlighter_props_menu(void)
864 switch (ui.brushes[TOOL_HIGHLIGHTER].thickness_no) {
866 gtk_check_menu_item_set_active(
867 GTK_CHECK_MENU_ITEM(GET_COMPONENT("highlighterFine")), TRUE);
869 case THICKNESS_MEDIUM:
870 gtk_check_menu_item_set_active(
871 GTK_CHECK_MENU_ITEM(GET_COMPONENT("highlighterMedium")), TRUE);
873 case THICKNESS_THICK:
874 gtk_check_menu_item_set_active(
875 GTK_CHECK_MENU_ITEM(GET_COMPONENT("highlighterThick")), TRUE);
880 void do_switch_page(int pg, gboolean rescroll)
888 /* re-show all the layers of the old page */
889 if (ui.cur_page != NULL)
890 for (i=0, list = ui.cur_page->layers; list!=NULL; i++, list = list->next) {
891 layer = (struct Layer *)list->data;
892 if (layer->group!=NULL)
893 gnome_canvas_item_show(GNOME_CANVAS_ITEM(layer->group));
896 ui.cur_page = g_list_nth_data(journal.pages, ui.pageno);
897 ui.layerno = ui.cur_page->nlayers-1;
898 ui.cur_layer = (struct Layer *)(g_list_last(ui.cur_page->layers)->data);
900 if (ui.progressive_bg) rescale_bg_pixmaps();
902 if (rescroll) { // scroll and force a refresh
903 gtk_adjustment_set_value(gtk_layout_get_vadjustment(GTK_LAYOUT(canvas)),
904 ui.cur_page->voffset*ui.zoom);
905 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
909 void update_page_stuff(void)
912 GtkComboBox *layerbox;
917 double vertpos, maxwidth;
921 // move the page groups to their rightful locations or hide them
922 if (ui.view_continuous) {
925 for (i=0, pglist = journal.pages; pglist!=NULL; i++, pglist = pglist->next) {
926 pg = (struct Page *)pglist->data;
927 if (pg->group!=NULL) {
928 pg->hoffset = 0.; pg->voffset = vertpos;
929 gnome_canvas_item_set(GNOME_CANVAS_ITEM(pg->group),
930 "x", pg->hoffset, "y", pg->voffset, NULL);
931 gnome_canvas_item_show(GNOME_CANVAS_ITEM(pg->group));
933 vertpos += pg->height + VIEW_CONTINUOUS_SKIP;
934 if (pg->width > maxwidth) maxwidth = pg->width;
936 vertpos -= VIEW_CONTINUOUS_SKIP;
937 gnome_canvas_set_scroll_region(canvas, 0, 0, maxwidth, vertpos);
939 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
940 pg = (struct Page *)pglist->data;
941 if (pg == ui.cur_page && pg->group!=NULL) {
942 pg->hoffset = 0.; pg->voffset = 0.;
943 gnome_canvas_item_set(GNOME_CANVAS_ITEM(pg->group),
944 "x", pg->hoffset, "y", pg->voffset, NULL);
945 gnome_canvas_item_show(GNOME_CANVAS_ITEM(pg->group));
947 if (pg->group!=NULL) gnome_canvas_item_hide(GNOME_CANVAS_ITEM(pg->group));
950 gnome_canvas_set_scroll_region(canvas, 0, 0, ui.cur_page->width, ui.cur_page->height);
953 // update the page / layer info at bottom of screen
955 spin = GTK_SPIN_BUTTON(GET_COMPONENT("spinPageNo"));
956 ui.in_update_page_stuff = TRUE; // avoid a bad retroaction
957 gtk_spin_button_set_range(spin, 1, journal.npages+1);
958 /* npages+1 will be used to create a new page at end */
959 gtk_spin_button_set_value(spin, ui.pageno+1);
960 g_snprintf(tmp, 10, " of %d", journal.npages);
961 gtk_label_set_text(GTK_LABEL(GET_COMPONENT("labelNumpages")), tmp);
963 layerbox = GTK_COMBO_BOX(GET_COMPONENT("comboLayer"));
964 if (ui.layerbox_length == 0) {
965 gtk_combo_box_prepend_text(layerbox, "Background");
966 ui.layerbox_length++;
968 while (ui.layerbox_length > ui.cur_page->nlayers+1) {
969 gtk_combo_box_remove_text(layerbox, 0);
970 ui.layerbox_length--;
972 while (ui.layerbox_length < ui.cur_page->nlayers+1) {
973 g_snprintf(tmp, 10, "Layer %d", ui.layerbox_length++);
974 gtk_combo_box_prepend_text(layerbox, tmp);
976 gtk_combo_box_set_active(layerbox, ui.cur_page->nlayers-1-ui.layerno);
977 ui.in_update_page_stuff = FALSE;
979 // update the paper-style menu radio buttons
981 if (ui.view_continuous)
982 gtk_check_menu_item_set_active(
983 GTK_CHECK_MENU_ITEM(GET_COMPONENT("viewContinuous")), TRUE);
985 gtk_check_menu_item_set_active(
986 GTK_CHECK_MENU_ITEM(GET_COMPONENT("viewOnePage")), TRUE);
988 if (ui.cur_page->bg->type == BG_SOLID) {
989 switch (ui.cur_page->bg->color_no) {
991 gtk_check_menu_item_set_active(
992 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorWhite")), TRUE);
995 gtk_check_menu_item_set_active(
996 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorYellow")), TRUE);
999 gtk_check_menu_item_set_active(
1000 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorPink")), TRUE);
1003 gtk_check_menu_item_set_active(
1004 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorOrange")), TRUE);
1007 gtk_check_menu_item_set_active(
1008 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorBlue")), TRUE);
1011 gtk_check_menu_item_set_active(
1012 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorGreen")), TRUE);
1015 gtk_check_menu_item_set_active(
1016 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorOther")), TRUE);
1019 switch (ui.cur_page->bg->ruling) {
1021 gtk_check_menu_item_set_active(
1022 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstylePlain")), TRUE);
1025 gtk_check_menu_item_set_active(
1026 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstyleLined")), TRUE);
1029 gtk_check_menu_item_set_active(
1030 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstyleRuled")), TRUE);
1033 gtk_check_menu_item_set_active(
1034 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstyleGraph")), TRUE);
1038 gtk_check_menu_item_set_active(
1039 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorNA")), TRUE);
1040 gtk_check_menu_item_set_active(
1041 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstyleNA")), TRUE);
1044 // enable/disable the page/layer menu items and toolbar buttons
1046 gtk_widget_set_sensitive(GET_COMPONENT("journalPaperColor"),
1047 ui.cur_page->bg->type == BG_SOLID);
1048 gtk_widget_set_sensitive(GET_COMPONENT("journalSetAsDefault"),
1049 ui.cur_page->bg->type == BG_SOLID);
1051 gtk_widget_set_sensitive(GET_COMPONENT("viewFirstPage"), ui.pageno!=0);
1052 gtk_widget_set_sensitive(GET_COMPONENT("viewPreviousPage"), ui.pageno!=0);
1053 gtk_widget_set_sensitive(GET_COMPONENT("viewNextPage"), TRUE);
1054 gtk_widget_set_sensitive(GET_COMPONENT("viewLastPage"), ui.pageno!=journal.npages-1);
1055 gtk_widget_set_sensitive(GET_COMPONENT("buttonFirstPage"), ui.pageno!=0);
1056 gtk_widget_set_sensitive(GET_COMPONENT("buttonPreviousPage"), ui.pageno!=0);
1057 gtk_widget_set_sensitive(GET_COMPONENT("buttonNextPage"), TRUE);
1058 gtk_widget_set_sensitive(GET_COMPONENT("buttonLastPage"), ui.pageno!=journal.npages-1);
1060 gtk_widget_set_sensitive(GET_COMPONENT("viewShowLayer"), ui.layerno!=ui.cur_page->nlayers-1);
1061 gtk_widget_set_sensitive(GET_COMPONENT("viewHideLayer"), ui.layerno>=0);
1063 gtk_widget_set_sensitive(GET_COMPONENT("editPaste"), ui.cur_layer!=NULL);
1064 gtk_widget_set_sensitive(GET_COMPONENT("buttonPaste"), ui.cur_layer!=NULL);
1067 void update_toolbar_and_menu(void)
1069 update_tool_buttons(); // takes care of other toolbar buttons as well
1071 update_color_menu();
1072 update_pen_props_menu();
1073 update_eraser_props_menu();
1074 update_highlighter_props_menu();
1076 gtk_toggle_tool_button_set_active(
1077 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonFullscreen")), ui.fullscreen);
1078 gtk_check_menu_item_set_active(
1079 GTK_CHECK_MENU_ITEM(GET_COMPONENT("viewFullscreen")), ui.fullscreen);
1082 void update_file_name(char *filename)
1085 if (ui.filename != NULL) g_free(ui.filename);
1086 ui.filename = filename;
1087 if (filename == NULL) {
1088 gtk_window_set_title(GTK_WINDOW (winMain), "Xournal");
1091 p = g_utf8_strrchr(filename, -1, '/');
1092 if (p == NULL) p = filename;
1093 else p = g_utf8_next_char(p);
1094 g_snprintf(tmp, 100, "Xournal - %s", p);
1095 gtk_window_set_title(GTK_WINDOW (winMain), tmp);
1098 void update_undo_redo_enabled(void)
1100 gtk_widget_set_sensitive(GET_COMPONENT("editUndo"), undo!=NULL);
1101 gtk_widget_set_sensitive(GET_COMPONENT("editRedo"), redo!=NULL);
1102 gtk_widget_set_sensitive(GET_COMPONENT("buttonUndo"), undo!=NULL);
1103 gtk_widget_set_sensitive(GET_COMPONENT("buttonRedo"), redo!=NULL);
1106 void update_copy_paste_enabled(void)
1108 gtk_widget_set_sensitive(GET_COMPONENT("editCut"), ui.selection!=NULL);
1109 gtk_widget_set_sensitive(GET_COMPONENT("editCopy"), ui.selection!=NULL);
1110 gtk_widget_set_sensitive(GET_COMPONENT("editDelete"), ui.selection!=NULL);
1111 gtk_widget_set_sensitive(GET_COMPONENT("buttonCut"), ui.selection!=NULL);
1112 gtk_widget_set_sensitive(GET_COMPONENT("buttonCopy"), ui.selection!=NULL);
1115 void set_cur_color(int color)
1117 ui.cur_brush->color_no = color;
1118 if (ui.toolno == TOOL_HIGHLIGHTER)
1119 ui.cur_brush->color_rgba = predef_colors_rgba[color] & HILITER_ALPHA_MASK;
1121 ui.cur_brush->color_rgba = predef_colors_rgba[color];
1124 void process_color_activate(GtkMenuItem *menuitem, int color)
1126 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1127 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1130 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1134 if (ui.toolno != TOOL_PEN && ui.toolno != TOOL_HIGHLIGHTER
1135 && ui.toolno != TOOL_TEXT && ui.selection == NULL) {
1136 ui.toolno = TOOL_PEN;
1137 ui.cur_brush = ui.brushes+TOOL_PEN;
1138 update_tool_buttons();
1142 if (ui.toolno == TOOL_PEN || ui.toolno == TOOL_HIGHLIGHTER)
1143 set_cur_color(color);
1145 // later add selection tools
1147 update_color_buttons();
1148 update_color_menu();
1152 void process_thickness_activate(GtkMenuItem *menuitem, int tool, int val)
1154 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1155 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1158 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1162 if (tool >= NUM_STROKE_TOOLS) {
1163 update_thickness_buttons(); // undo illegal button selection
1167 if (ui.brushes[tool].thickness_no == val) return; // avoid loops
1168 ui.brushes[tool].thickness_no = val;
1169 ui.brushes[tool].thickness = predef_thickness[tool][val];
1171 update_thickness_buttons();
1172 if (tool == TOOL_PEN) update_pen_props_menu();
1173 if (tool == TOOL_ERASER) update_eraser_props_menu();
1174 if (tool == TOOL_HIGHLIGHTER) update_highlighter_props_menu();
1178 void process_papercolor_activate(GtkMenuItem *menuitem, int color)
1180 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1183 if (ui.cur_page->bg->type != BG_SOLID) {
1184 gtk_check_menu_item_set_active(
1185 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorNA")), TRUE);
1189 if (ui.cur_page->bg->color_no == color) return;
1193 undo->type = ITEM_NEW_BG_ONE;
1194 undo->page = ui.cur_page;
1195 undo->bg = (struct Background *)g_memdup(ui.cur_page->bg, sizeof(struct Background));
1196 undo->bg->canvas_item = NULL;
1198 ui.cur_page->bg->color_no = color;
1199 ui.cur_page->bg->color_rgba = predef_bgcolors_rgba[color];
1200 update_canvas_bg(ui.cur_page);
1203 void process_paperstyle_activate(GtkMenuItem *menuitem, int style)
1205 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1208 if (ui.cur_page->bg->type == BG_SOLID && ui.cur_page->bg->ruling == style)
1213 undo->type = ITEM_NEW_BG_ONE;
1214 undo->page = ui.cur_page;
1215 undo->bg = (struct Background *)g_memdup(ui.cur_page->bg, sizeof(struct Background));
1216 undo->bg->canvas_item = NULL;
1218 if (ui.cur_page->bg->type != BG_SOLID) {
1219 ui.cur_page->bg->type = BG_SOLID;
1220 ui.cur_page->bg->color_no = COLOR_WHITE;
1221 ui.cur_page->bg->color_rgba = predef_bgcolors_rgba[COLOR_WHITE];
1222 ui.cur_page->bg->filename = NULL;
1223 ui.cur_page->bg->pixbuf = NULL;
1224 update_page_stuff();
1227 ui.cur_page->bg->ruling = style;
1228 update_canvas_bg(ui.cur_page);
1231 gboolean ok_to_close(void)
1234 GtkResponseType response;
1237 if (ui.saved) return TRUE;
1238 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
1239 GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, "Save changes to '%s'?",
1240 (ui.filename!=NULL) ? ui.filename:"Untitled");
1241 gtk_dialog_add_button(GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
1242 response = gtk_dialog_run(GTK_DIALOG (dialog));
1243 gtk_widget_destroy(dialog);
1244 if (response == GTK_RESPONSE_CANCEL || response == GTK_RESPONSE_DELETE_EVENT)
1245 return FALSE; // aborted
1246 if (response == GTK_RESPONSE_YES) {
1247 on_fileSave_activate(NULL, NULL);
1248 if (!ui.saved) return FALSE; // if save failed, then we abort
1253 // test if we're still busy loading a PDF background file
1254 gboolean page_ops_forbidden(void)
1256 return (bgpdf.status != STATUS_NOT_INIT && bgpdf.create_pages);
1259 // selection / clipboard stuff
1261 void reset_selection(void)
1263 if (ui.selection == NULL) return;
1264 if (ui.selection->canvas_item != NULL)
1265 gtk_object_destroy(GTK_OBJECT(ui.selection->canvas_item));
1266 g_list_free(ui.selection->items);
1267 g_free(ui.selection);
1268 ui.selection = NULL;
1269 update_copy_paste_enabled();
1272 void move_journal_items_by(GList *itemlist, double dx, double dy)
1278 while (itemlist!=NULL) {
1279 item = (struct Item *)itemlist->data;
1280 if (item->type == ITEM_STROKE) {
1281 for (pt=item->path->coords, i=0; i<item->path->num_points; i++, pt+=2)
1282 { pt[0] += dx; pt[1] += dy; }
1283 item->bbox.left += dx;
1284 item->bbox.right += dx;
1285 item->bbox.top += dy;
1286 item->bbox.bottom += dy;
1288 itemlist = itemlist->next;