/* * FIG : Facility for Interactive Generation of figures * Copyright (c) 1985-1988 by Supoj Sutanthavibul * Parts Copyright (c) 1989-2002 by Brian V. Smith * Parts Copyright (c) 1991 by Paul King * * Any party obtaining a copy of these files is granted, free of charge, a * full and unrestricted irrevocable, world-wide, paid up, royalty-free, * nonexclusive right and license to deal in this software and documentation * files (the "Software"), including without limitation the rights to use, * copy, modify, merge, publish distribute, sublicense and/or sell copies of * the Software, and to permit persons who receive copies from any such * party to do so, with the only requirement being that the above copyright * and this permission notice remain intact. * */ #include "fig.h" #include "resources.h" #include "object.h" #include "paintop.h" #include "e_copy.h" #include "u_drag.h" #include "u_draw.h" #include "u_elastic.h" #include "u_list.h" #include "u_create.h" #include "u_undo.h" #include "mode.h" #include "w_canvas.h" #include "w_drawprim.h" #include "w_zoom.h" static void array_place_line(), place_line(), place_line_x(), cancel_line(); static void array_place_arc(), place_arc(), place_arc_x(), cancel_drag_arc(); static void array_place_spline(), place_spline(), place_spline_x(), cancel_spline(); static void array_place_ellipse(), place_ellipse(), place_ellipse_x(), cancel_ellipse(); static void array_place_text(), place_text(), place_text_x(), cancel_text(); static void array_place_compound(), place_compound(), place_compound_x(), cancel_drag_compound(); /***************************** ellipse section ************************/ void init_ellipsedragging(e, x, y) F_ellipse *e; int x, y; { new_e = e; fix_x = cur_x = x; fix_y = cur_y = y; cur_angle = e->angle; x1off = (e->center.x - e->radiuses.x) - cur_x; x2off = (e->center.x + e->radiuses.x) - cur_x; y1off = (e->center.y - e->radiuses.y) - cur_y; y2off = (e->center.y + e->radiuses.y) - cur_y; canvas_locmove_proc = moving_ellipse; canvas_ref_proc = elastic_moveellipse; canvas_leftbut_proc = place_ellipse; canvas_middlebut_proc = array_place_ellipse; canvas_rightbut_proc = cancel_ellipse; set_action_on(); elastic_moveellipse(); } static void cancel_ellipse() { canvas_ref_proc = canvas_locmove_proc = null_proc; elastic_moveellipse(); /* erase last lengths if appres.showlengths is true */ erase_lengths(); if (return_proc == copy_selected) { free_ellipse(&new_e); } else { list_add_ellipse(&objects.ellipses, new_e); redisplay_ellipse(new_e); } /* turn back on all relevant markers */ update_markers(new_objmask); (*return_proc) (); draw_mousefun_canvas(); } static void array_place_ellipse(x, y) int x, y; { int i, j, delta_x, delta_y, start_x, start_y; int nx, ny; F_ellipse *save_ellipse; elastic_moveellipse(); /* erase last lengths if appres.showlengths is true */ erase_lengths(); tail(&objects, &object_tails); save_ellipse = new_e; if ((!cur_numxcopies) && (!cur_numycopies)) { place_ellipse(x, y); } else { delta_x = cur_x - fix_x; delta_y = cur_y - fix_y; start_x = cur_x - delta_x; start_y = cur_y - delta_y; if ((cur_numxcopies < 2) && (cur_numycopies < 2)) { /* special cases */ if (cur_numxcopies > 0) { place_ellipse_x(start_x+delta_x, start_y); new_e = copy_ellipse(cur_e); } if (cur_numycopies > 0) { place_ellipse_x(start_x, start_y+delta_y); new_e = copy_ellipse(cur_e); } } else { nx = cur_numxcopies; if (nx == 0) nx++; ny = cur_numycopies; if (ny == 0) ny++; for (i = 0, x = start_x; i < nx; i++, x+=delta_x) { for (j = 0, y = start_y; j < ny; j++, y+=delta_y) { if (i || j ) { place_ellipse_x(x, y); new_e = copy_ellipse(cur_e); } } } } } /* put all new ellipses in the saved objects structure for undo */ saved_objects.ellipses = save_ellipse; set_action_object(F_ADD, O_ALL_OBJECT); /* turn back on all relevant markers */ update_markers(new_objmask); } static void place_ellipse(x, y) int x, y; { elastic_moveellipse(); /* erase last lengths if appres.showlengths is true */ erase_lengths(); place_ellipse_x(x, y); } static void place_ellipse_x(x, y) int x, y; { canvas_leftbut_proc = null_proc; canvas_middlebut_proc = null_proc; canvas_rightbut_proc = null_proc; canvas_locmove_proc = null_proc; canvas_ref_proc = null_proc; adjust_pos(x, y, fix_x, fix_y, &x, &y); translate_ellipse(new_e, x - fix_x, y - fix_y); if (return_proc == copy_selected) { add_ellipse(new_e); } else { list_add_ellipse(&objects.ellipses, new_e); clean_up(); set_lastposition(fix_x, fix_y); set_newposition(x, y); set_action_object(F_MOVE, O_ELLIPSE); set_latestellipse(new_e); set_modifiedflag(); } redisplay_ellipse(new_e); /* turn back on all relevant markers */ update_markers(new_objmask); (*return_proc) (); draw_mousefun_canvas(); } /***************************** arc section *******************/ void init_arcdragging(a, x, y) F_arc *a; int x, y; { new_a = a; fix_x = cur_x = x; fix_y = cur_y = y; canvas_locmove_proc = moving_arc; canvas_ref_proc = elastic_movenewarc; canvas_leftbut_proc = place_arc; canvas_middlebut_proc = array_place_arc; canvas_rightbut_proc = cancel_drag_arc; set_action_on(); elastic_movearc(new_a); } static void cancel_drag_arc() { canvas_ref_proc = canvas_locmove_proc = null_proc; elastic_movearc(new_a); /* erase last lengths if appres.showlengths is true */ erase_lengths(); if (return_proc == copy_selected) { free_arc(&new_a); } else { list_add_arc(&objects.arcs, new_a); redisplay_arc(new_a); } /* turn back on all relevant markers */ update_markers(new_objmask); (*return_proc) (); draw_mousefun_canvas(); } static void array_place_arc(x, y) int x, y; { int i, j, delta_x, delta_y, start_x, start_y; int nx, ny; F_arc *save_arc; elastic_movearc(new_a); /* erase last lengths if appres.showlengths is true */ erase_lengths(); tail(&objects, &object_tails); save_arc = new_a; if ((!cur_numxcopies) && (!cur_numycopies)) { place_arc(x, y); } else { delta_x = cur_x - fix_x; delta_y = cur_y - fix_y; start_x = cur_x - delta_x; start_y = cur_y - delta_y; if ((cur_numxcopies < 2) && (cur_numycopies < 2)) { /* special cases */ if (cur_numxcopies > 0) { place_arc_x(start_x+delta_x, start_y); new_a = copy_arc(cur_a); } if (cur_numycopies > 0) { place_arc_x(start_x, start_y+delta_y); new_a = copy_arc(cur_a); } } else { nx = cur_numxcopies; if (nx == 0) nx++; ny = cur_numycopies; if (ny == 0) ny++; for (i = 0, x = start_x; i < nx; i++, x+=delta_x) { for (j = 0, y = start_y; j < ny; j++, y+=delta_y) { if (i || j ) { place_arc_x(x, y); new_a = copy_arc(cur_a); } } } } } /* put all new arcs in the saved objects structure for undo */ saved_objects.arcs = save_arc; set_action_object(F_ADD, O_ALL_OBJECT); /* turn back on all relevant markers */ update_markers(new_objmask); } static void place_arc(x, y) int x, y; { elastic_movearc(new_a); /* erase last lengths if appres.showlengths is true */ erase_lengths(); place_arc_x(x, y); } static void place_arc_x(x, y) int x, y; { canvas_leftbut_proc = null_proc; canvas_middlebut_proc = null_proc; canvas_rightbut_proc = null_proc; canvas_locmove_proc = null_proc; canvas_ref_proc = null_proc; adjust_pos(x, y, fix_x, fix_y, &x, &y); translate_arc(new_a, x - fix_x, y - fix_y); if (return_proc == copy_selected) { add_arc(new_a); } else { list_add_arc(&objects.arcs, new_a); clean_up(); set_lastposition(fix_x, fix_y); set_newposition(x, y); set_action_object(F_MOVE, O_ARC); set_latestarc(new_a); set_modifiedflag(); } redisplay_arc(new_a); /* turn back on all relevant markers */ update_markers(new_objmask); (*return_proc) (); draw_mousefun_canvas(); } /************************* line section **********************/ void init_linedragging(l, x, y) F_line *l; int x, y; { int xmin, ymin, xmax, ymax; new_l = l; cur_x = fix_x = x; cur_y = fix_y = y; canvas_locmove_proc = moving_line; canvas_ref_proc = elastic_movenewline; canvas_leftbut_proc = place_line; canvas_middlebut_proc = array_place_line; canvas_rightbut_proc = cancel_line; set_action_on(); if (l->type == T_BOX || l->type == T_ARCBOX || l->type == T_PICTURE) { line_bound(l, &xmin, &ymin, &xmax, &ymax); get_links(xmin, ymin, xmax, ymax); } elastic_moveline(new_l->points); } static void cancel_line() { canvas_ref_proc = canvas_locmove_proc = null_proc; elastic_moveline(new_l->points); /* erase last lengths if appres.showlengths is true */ erase_lengths(); free_linkinfo(&cur_links); if (return_proc == copy_selected) { free_line(&new_l); } else { list_add_line(&objects.lines, new_l); redisplay_line(new_l); } /* turn back on all relevant markers */ update_markers(new_objmask); (*return_proc) (); draw_mousefun_canvas(); } static void array_place_line(x, y) int x, y; { int i, j, delta_x, delta_y, start_x, start_y; int nx, ny; F_line *save_line; elastic_moveline(new_l->points); /* erase last lengths if appres.showlengths is true */ erase_lengths(); tail(&objects, &object_tails); save_line = new_l; if ((cur_numxcopies==0) && (cur_numycopies==0)) { place_line(x, y); } else { delta_x = cur_x - fix_x; delta_y = cur_y - fix_y; start_x = cur_x - delta_x; start_y = cur_y - delta_y; if ((cur_numxcopies < 2) && (cur_numycopies < 2)) { /* special cases */ if (cur_numxcopies > 0) { place_line_x(start_x+delta_x, start_y); new_l = copy_line(cur_l); } if (cur_numycopies > 0) { place_line_x(start_x, start_y+delta_y); new_l = copy_line(cur_l); } } else { nx = cur_numxcopies; if (nx == 0) nx++; ny = cur_numycopies; if (ny == 0) ny++; for (i = 0, x = start_x; i < nx; i++, x+=delta_x) { for (j = 0, y = start_y; j < ny; j++, y+=delta_y) { if (i || j ) { place_line_x(x, y); new_l = copy_line(cur_l); } } } } } /* put all new lines in the saved objects structure for undo */ saved_objects.lines = save_line; set_action_object(F_ADD, O_ALL_OBJECT); /* turn back on all relevant markers */ update_markers(new_objmask); } static void place_line(x, y) int x, y; { elastic_moveline(new_l->points); /* erase last lengths if appres.showlengths is true */ erase_lengths(); place_line_x(x, y); } static void place_line_x(x, y) int x, y; { int dx, dy; canvas_leftbut_proc = null_proc; canvas_middlebut_proc = null_proc; canvas_rightbut_proc = null_proc; canvas_locmove_proc = null_proc; canvas_ref_proc = null_proc; adjust_pos(x, y, fix_x, fix_y, &x, &y); dx = x - fix_x; dy = y - fix_y; translate_line(new_l, dx, dy); clean_up(); set_latestline(new_l); if (return_proc == copy_selected) { add_line(new_l); adjust_links(cur_linkmode, cur_links, dx, dy, 0, 0, 1.0, 1.0, True); free_linkinfo(&cur_links); } else { list_add_line(&objects.lines, new_l); adjust_links(cur_linkmode, cur_links, dx, dy, 0, 0, 1.0, 1.0, False); set_lastposition(fix_x, fix_y); set_newposition(x, y); set_lastlinkinfo(cur_linkmode, cur_links); cur_links = NULL; set_action_object(F_MOVE, O_POLYLINE); } set_modifiedflag(); redisplay_line(new_l); /* turn back on all relevant markers */ update_markers(new_objmask); (*return_proc) (); draw_mousefun_canvas(); } /************************ text section **************************/ static PR_SIZE txsize; void init_textdragging(t, x, y) F_text *t; int x, y; { float cw,cw2; int x1, y1; new_t = t; fix_x = cur_x = x; fix_y = cur_y = y; x1 = new_t->base_x; y1 = new_t->base_y; /* adjust fix_x/y so that text will fall on grid if grid is on */ round_coords(x1,y1); fix_x += new_t->base_x - x1; fix_y += new_t->base_y - y1; x1off = x1-x; /*new_t->base_x - x;*/ y1off = y1-y; /*new_t->base_y - y;*/ if (t->type == T_CENTER_JUSTIFIED || t->type == T_RIGHT_JUSTIFIED) { txsize = textsize(t->fontstruct, strlen(t->cstring), t->cstring); if (t->type == T_CENTER_JUSTIFIED) { cw2 = txsize.length/2.0/display_zoomscale; x1off = round(x1off - cos((double)t->angle)*cw2); y1off = round(y1off + sin((double)t->angle)*cw2); } else { /* T_RIGHT_JUSTIFIED */ cw = 1.0*txsize.length/display_zoomscale; x1off = round(x1off - cos((double)t->angle)*cw); y1off = round(y1off + sin((double)t->angle)*cw); } } canvas_locmove_proc = moving_text; canvas_ref_proc = elastic_movetext; canvas_leftbut_proc = place_text; canvas_middlebut_proc = array_place_text; canvas_rightbut_proc = cancel_text; elastic_movetext(); set_action_on(); } static void array_place_text(x, y) int x, y; { int i, j, delta_x, delta_y, start_x, start_y; int nx, ny; F_text *save_text; elastic_movetext(); /* erase last lengths if appres.showlengths is true */ erase_lengths(); tail(&objects, &object_tails); save_text = new_t; if ((!cur_numxcopies) && (!cur_numycopies)) { place_text(x, y); } else { delta_x = cur_x - fix_x; delta_y = cur_y - fix_y; start_x = cur_x - delta_x; start_y = cur_y - delta_y; if ((cur_numxcopies < 2) && (cur_numycopies < 2)) { /* special cases */ if (cur_numxcopies > 0) { place_text_x(start_x+delta_x, start_y); new_t = copy_text(cur_t); } if (cur_numycopies > 0) { place_text_x(start_x, start_y+delta_y); new_t = copy_text(cur_t); } } else { nx = cur_numxcopies; if (nx == 0) nx++; ny = cur_numycopies; if (ny == 0) ny++; for (i = 0, x = start_x; i < nx; i++, x+=delta_x) { for (j = 0, y = start_y; j < ny; j++, y+=delta_y) { if (i || j ) { place_text_x(x, y); new_t = copy_text(cur_t); } } } } } /* put all new texts in the saved objects structure for undo */ saved_objects.texts = save_text; set_action_object(F_ADD, O_ALL_OBJECT); /* turn back on all relevant markers */ update_markers(new_objmask); } static void cancel_text() { canvas_ref_proc = canvas_locmove_proc = null_proc; elastic_movetext(); /* erase last lengths if appres.showlengths is true */ erase_lengths(); if (return_proc == copy_selected) { free_text(&new_t); } else { list_add_text(&objects.texts, new_t); redisplay_text(new_t); } /* turn back on all relevant markers */ update_markers(new_objmask); (*return_proc) (); draw_mousefun_canvas(); } static void place_text(x, y) int x, y; { elastic_movetext(); /* erase last lengths if appres.showlengths is true */ erase_lengths(); place_text_x(x, y); } static void place_text_x(x, y) int x, y; { canvas_leftbut_proc = null_proc; canvas_middlebut_proc = null_proc; canvas_rightbut_proc = null_proc; canvas_locmove_proc = null_proc; canvas_ref_proc = null_proc; adjust_pos(x, y, fix_x, fix_y, &x, &y); translate_text(new_t, x - fix_x, y - fix_y); if (return_proc == copy_selected) { add_text(new_t); } else { list_add_text(&objects.texts, new_t); clean_up(); set_lastposition(fix_x, fix_y); set_newposition(x, y); set_action_object(F_MOVE, O_TEXT); set_latesttext(new_t); set_modifiedflag(); } redisplay_text(new_t); /* turn back on all relevant markers */ update_markers(new_objmask); (*return_proc) (); draw_mousefun_canvas(); } /************************* spline section **********************/ void init_splinedragging(s, x, y) F_spline *s; int x, y; { new_s = s; cur_x = fix_x = x; cur_y = fix_y = y; canvas_locmove_proc = moving_spline; canvas_ref_proc = elastic_movenewspline; canvas_leftbut_proc = place_spline; canvas_middlebut_proc = array_place_spline; canvas_rightbut_proc = cancel_spline; set_action_on(); elastic_moveline(new_s->points); } static void cancel_spline() { canvas_ref_proc = canvas_locmove_proc = null_proc; elastic_moveline(new_s->points); /* erase last lengths if appres.showlengths is true */ erase_lengths(); if (return_proc == copy_selected) { free_spline(&new_s); } else { list_add_spline(&objects.splines, new_s); redisplay_spline(new_s); } /* turn back on all relevant markers */ update_markers(new_objmask); (*return_proc) (); draw_mousefun_canvas(); } static void array_place_spline(x, y) int x, y; { int i, j, delta_x, delta_y, start_x, start_y; int nx, ny; F_spline *save_spline; elastic_moveline(new_s->points); /* erase last lengths if appres.showlengths is true */ erase_lengths(); tail(&objects, &object_tails); save_spline = new_s; if ((!cur_numxcopies) && (!cur_numycopies)) { place_spline(x, y); } else { delta_x = cur_x - fix_x; delta_y = cur_y - fix_y; start_x = cur_x - delta_x; start_y = cur_y - delta_y; if ((cur_numxcopies < 2) && (cur_numycopies < 2)) { /* special cases */ if (cur_numxcopies > 0) { place_spline_x(start_x+delta_x, start_y); new_s = copy_spline(cur_s); } if (cur_numycopies > 0) { place_spline_x(start_x, start_y+delta_y); new_s = copy_spline(cur_s); } } else { nx = cur_numxcopies; if (nx == 0) nx++; ny = cur_numycopies; if (ny == 0) ny++; for (i = 0, x = start_x; i < nx; i++, x+=delta_x) { for (j = 0, y = start_y; j < ny; j++, y+=delta_y) { if (i || j ) { place_spline_x(x, y); new_s = copy_spline(cur_s); } } } } } /* put all new splines in the saved objects structure for undo */ saved_objects.splines = save_spline; set_action_object(F_ADD, O_ALL_OBJECT); /* turn back on all relevant markers */ update_markers(new_objmask); } static void place_spline(x, y) int x, y; { elastic_moveline(new_s->points); /* erase last lengths if appres.showlengths is true */ erase_lengths(); place_spline_x(x, y); } static void place_spline_x(x, y) int x, y; { canvas_leftbut_proc = null_proc; canvas_middlebut_proc = null_proc; canvas_rightbut_proc = null_proc; canvas_locmove_proc = null_proc; canvas_ref_proc = null_proc; adjust_pos(x, y, fix_x, fix_y, &x, &y); translate_spline(new_s, x - fix_x, y - fix_y); if (return_proc == copy_selected) { add_spline(new_s); } else { list_add_spline(&objects.splines, new_s); clean_up(); set_lastposition(fix_x, fix_y); set_newposition(x, y); set_action_object(F_MOVE, O_SPLINE); set_latestspline(new_s); set_modifiedflag(); } redisplay_spline(new_s); /* turn back on all relevant markers */ update_markers(new_objmask); (*return_proc) (); draw_mousefun_canvas(); } /***************************** Compound section *******************/ void init_compounddragging(c, x, y) F_compound *c; int x, y; { new_c = c; fix_x = cur_x = x; fix_y = cur_y = y; x1off = c->nwcorner.x - x; x2off = c->secorner.x - x; y1off = c->nwcorner.y - y; y2off = c->secorner.y - y; canvas_locmove_proc = moving_box; canvas_ref_proc = elastic_movebox; canvas_leftbut_proc = place_compound; canvas_middlebut_proc = array_place_compound; canvas_rightbut_proc = cancel_drag_compound; set_action_on(); get_interior_links(c->nwcorner.x, c->nwcorner.y, c->secorner.x, c->secorner.y); elastic_movebox(); } static void cancel_drag_compound() { canvas_ref_proc = canvas_locmove_proc = null_proc; elastic_movebox(); /* erase last lengths if appres.showlengths is true */ erase_lengths(); free_linkinfo(&cur_links); if (return_proc == copy_selected) { free_compound(&new_c); } else { list_add_compound(&objects.compounds, new_c); redisplay_compound(new_c); } /* turn back on all relevant markers */ update_markers(new_objmask); (*return_proc) (); draw_mousefun_canvas(); } static void array_place_compound(x, y) int x, y; { int i, j, delta_x, delta_y, start_x, start_y; int nx, ny; F_compound *save_compound; elastic_movebox(); /* erase last lengths if appres.showlengths is true */ erase_lengths(); tail(&objects, &object_tails); save_compound = new_c; if ((!cur_numxcopies) && (!cur_numycopies)) { place_compound(x, y); } else { delta_x = cur_x - fix_x; delta_y = cur_y - fix_y; start_x = cur_x - delta_x; start_y = cur_y - delta_y; if ((cur_numxcopies < 2) && (cur_numycopies < 2)) { /* special cases */ if (cur_numxcopies > 0) { place_compound_x(start_x+delta_x, start_y); new_c = copy_compound(cur_c); } if (cur_numycopies > 0) { place_compound_x(start_x, start_y+delta_y); new_c = copy_compound(cur_c); } } else { nx = cur_numxcopies; if (nx == 0) nx++; ny = cur_numycopies; if (ny == 0) ny++; for (i = 0, x = start_x; i < nx; i++, x+=delta_x) { for (j = 0, y = start_y; j < ny; j++, y+=delta_y) { if (i || j ) { place_compound_x(x, y); new_c = copy_compound(cur_c); } } } } } /* put all new compounds in the saved objects structure for undo */ saved_objects.compounds = save_compound; set_action_object(F_ADD, O_ALL_OBJECT); /* turn back on all relevant markers */ update_markers(new_objmask); } static void place_compound(x, y) int x, y; { elastic_movebox(); /* erase last lengths if appres.showlengths is true */ erase_lengths(); place_compound_x(x, y); } static void place_compound_x(x, y) int x, y; { int dx, dy; canvas_leftbut_proc = null_proc; canvas_middlebut_proc = null_proc; canvas_rightbut_proc = null_proc; canvas_locmove_proc = null_proc; canvas_ref_proc = null_proc; adjust_pos(x, y, fix_x, fix_y, &x, &y); dx = x - fix_x; dy = y - fix_y; translate_compound(new_c, dx, dy); clean_up(); set_latestcompound(new_c); if (return_proc == copy_selected) { add_compound(new_c); adjust_links(cur_linkmode, cur_links, dx, dy, 0, 0, 1.0, 1.0, True); free_linkinfo(&cur_links); } else { list_add_compound(&objects.compounds, new_c); adjust_links(cur_linkmode, cur_links, dx, dy, 0, 0, 1.0, 1.0, False); set_lastposition(fix_x, fix_y); set_newposition(x, y); set_lastlinkinfo(cur_linkmode, cur_links); cur_links = NULL; set_action_object(F_MOVE, O_COMPOUND); } set_modifiedflag(); redisplay_compound(new_c); /* turn back on all relevant markers */ update_markers(new_objmask); (*return_proc) (); draw_mousefun_canvas(); }