1 /*
2  * FIG : Facility for Interactive Generation of figures
3  * Copyright (c) 1985-1988 by Supoj Sutanthavibul
4  * Parts Copyright (c) 1989-2015 by Brian V. Smith
5  * Parts Copyright (c) 1991 by Paul King
6  * Parts Copyright (c) 2016-2020 by Thomas Loimer
7  *
8  * Any party obtaining a copy of these files is granted, free of charge, a
9  * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
10  * nonexclusive right and license to deal in this software and documentation
11  * files (the "Software"), including without limitation the rights to use,
12  * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
13  * the Software, and to permit persons who receive copies from any such
14  * party to do so, with the only requirement being that the above copyright
15  * and this permission notice remain intact.
16  *
17  */
18 
19 #include "e_arrow.h"
20 
21 #include <stdlib.h>
22 
23 #include "resources.h"
24 #include "mode.h"
25 #include "object.h"
26 #include "paintop.h"
27 #include "u_create.h"
28 #include "u_draw.h"
29 #include "u_redraw.h"
30 #include "u_search.h"
31 #include "u_undo.h"
32 #include "w_canvas.h"
33 #include "w_cursor.h"
34 #include "w_mousefun.h"
35 
36 
37 static void	add_arrow_head(F_line *obj, int type, int x, int y,
38 				F_point *p, F_point *q, int pnum);
39 static void	delete_arrow_head(F_line *obj, int type, int x, int y,
40 				F_point *p, F_point *q, int pnum);
41 static void	add_linearrow(F_line *line, F_point *prev_point,
42 				F_point *selected_point);
43 static void	add_arcarrow(F_arc *arc, int point_num);
44 static void	add_splinearrow(F_spline *spline, F_point *prev_point,
45 				F_point *selected_point);
46 
47 
48 
49 void
arrow_head_selected(void)50 arrow_head_selected(void)
51 {
52     set_mousefun("add arrow", "delete arrow", "", LOC_OBJ, LOC_OBJ, LOC_OBJ);
53     canvas_kbd_proc = null_proc;
54     canvas_locmove_proc = null_proc;
55     canvas_ref_proc = null_proc;
56     init_searchproc_left(add_arrow_head);
57     init_searchproc_middle(delete_arrow_head);
58     canvas_leftbut_proc = point_search_left;
59     canvas_middlebut_proc = point_search_middle;
60     canvas_rightbut_proc = null_proc;
61     set_cursor(pick9_cursor);
62     reset_action_on();
63 }
64 
65 static void
add_arrow_head(F_line * obj,int type,int x,int y,F_point * p,F_point * q,int pnum)66 add_arrow_head(F_line *obj, int type, int x, int y, F_point *p, F_point *q,
67 		int pnum)
68 {
69 	(void)x;
70 	(void)y;
71 
72 	switch (type) {
73 	case O_POLYLINE:
74 		cur_l = (F_line *) obj;
75 		add_linearrow(cur_l, p, q);
76 		break;
77 	case O_SPLINE:
78 		cur_s = (F_spline *) obj;
79 		add_splinearrow(cur_s, p, q);
80 		break;
81 	case O_ARC:
82 		cur_a = (F_arc *) obj;
83 		add_arcarrow(cur_a, pnum);
84 		break;
85 	}
86 }
87 
88 static void
delete_arrow_head(F_line * obj,int type,int x,int y,F_point * p,F_point * q,int pnum)89 delete_arrow_head(F_line *obj, int type, int x, int y, F_point *p, F_point *q,
90 		int pnum)
91 {
92 	(void)x;
93 	(void)y;
94 
95 	switch (type) {
96 	case O_POLYLINE:
97 		cur_l = (F_line *) obj;
98 		delete_linearrow(cur_l, p, q);
99 		break;
100 	case O_SPLINE:
101 		cur_s = (F_spline *) obj;
102 		delete_splinearrow(cur_s, p, q);
103 		break;
104 	case O_ARC:
105 		cur_a = (F_arc *) obj;
106 		delete_arcarrow(cur_a, pnum);
107 		break;
108 	}
109 }
110 
111 static void
add_linearrow(F_line * line,F_point * prev_point,F_point * selected_point)112 add_linearrow(F_line *line, F_point *prev_point, F_point *selected_point)
113 {
114     if (line->points->next == NULL)
115 	return;			/* A single point line */
116 
117     if (prev_point == NULL) {	/* selected_point is the first point */
118 	if (line->back_arrow)
119 	    return;
120 	line->back_arrow = backward_arrow();
121 	redisplay_line(line);
122     } else if (selected_point->next == NULL) {	/* forward arrow */
123 	if (line->for_arrow)
124 	    return;
125 	line->for_arrow = forward_arrow();
126 	redisplay_line(line);
127     } else
128 	return;
129     clean_up();
130     set_last_prevpoint(prev_point);
131     set_last_selectedpoint(selected_point);
132     set_latestline(line);
133     set_action_object(F_ADD_ARROW_HEAD, O_POLYLINE);
134     set_modifiedflag();
135 }
136 
137 static void
add_arcarrow(F_arc * arc,int point_num)138 add_arcarrow(F_arc *arc, int point_num)
139 {
140 
141     /* only allow arrowheads on open arc */
142     if (arc->type == T_PIE_WEDGE_ARC)
143 	return;
144     if (point_num == 0) {	/* backward arrow  */
145 	if (arc->back_arrow)
146 	    return;
147 	arc->back_arrow = backward_arrow();
148 	redisplay_arc(arc);
149     } else if (point_num == 2) {/* for_arrow  */
150 	if (arc->for_arrow)
151 	    return;
152 	arc->for_arrow = forward_arrow();
153 	redisplay_arc(arc);
154     } else
155 	return;
156     clean_up();
157     set_last_arcpointnum(point_num);
158     set_latestarc(arc);
159     set_action_object(F_ADD_ARROW_HEAD, O_ARC);
160     set_modifiedflag();
161 }
162 
163 static void
add_splinearrow(F_spline * spline,F_point * prev_point,F_point * selected_point)164 add_splinearrow(F_spline *spline, F_point *prev_point, F_point *selected_point)
165 {
166     if (prev_point == NULL) {	/* add backward arrow */
167 	if (spline->back_arrow)
168 	    return;
169 	spline->back_arrow = backward_arrow();
170 	redisplay_spline(spline);
171     } else if (selected_point->next == NULL) {	/* add forward arrow */
172 	if (spline->for_arrow)
173 	    return;
174 	spline->for_arrow = forward_arrow();
175 	redisplay_spline(spline);
176     }
177     clean_up();
178     set_last_prevpoint(prev_point);
179     set_last_selectedpoint(selected_point);
180     set_latestspline(spline);
181     set_action_object(F_ADD_ARROW_HEAD, O_SPLINE);
182     set_modifiedflag();
183 }
184 
185 void
delete_linearrow(F_line * line,F_point * prev_point,F_point * selected_point)186 delete_linearrow(F_line *line, F_point *prev_point, F_point *selected_point)
187 {
188     if (line->points->next == NULL)
189 	return;			/* A single point line */
190 
191     if (prev_point == NULL) {	/* selected_point is the first point */
192 	if (!line->back_arrow)
193 	    return;
194 	draw_line(line, ERASE);
195 	saved_back_arrow=line->back_arrow;
196 	if (saved_for_arrow && saved_for_arrow != line->for_arrow)
197 	    free((char *) saved_for_arrow);
198 	saved_for_arrow = NULL;
199 	line->back_arrow = NULL;
200 	redisplay_line(line);
201     } else if (selected_point->next == NULL) {	/* forward arrow */
202 	if (!line->for_arrow)
203 	    return;
204 	draw_line(line, ERASE);
205 	saved_for_arrow=line->for_arrow;
206 	if (saved_back_arrow && saved_back_arrow != line->back_arrow)
207 	    free((char *) saved_back_arrow);
208 	saved_back_arrow = NULL;
209 	line->for_arrow = NULL;
210 	redisplay_line(line);
211     } else
212 	return;
213     clean_up();
214     set_last_prevpoint(prev_point);
215     set_last_selectedpoint(selected_point);
216     set_latestline(line);
217     set_action_object(F_DELETE_ARROW_HEAD, O_POLYLINE);
218     set_modifiedflag();
219 }
220 
221 void
delete_arcarrow(F_arc * arc,int point_num)222 delete_arcarrow(F_arc *arc, int point_num)
223 {
224     if (arc->type == T_PIE_WEDGE_ARC)
225 	return;;
226     if (point_num == 0) {	/* backward arrow  */
227 	if (!arc->back_arrow)
228 	    return;
229 	draw_arc(arc, ERASE);
230 	saved_back_arrow=arc->back_arrow;
231 	if (saved_for_arrow && saved_for_arrow != arc->for_arrow)
232 	    free((char *) saved_for_arrow);
233 	saved_for_arrow = NULL;
234 	arc->back_arrow = NULL;
235 	redisplay_arc(arc);
236     } else if (point_num == 2) {/* for_arrow  */
237 	if (!arc->for_arrow)
238 	    return;
239 	draw_arc(arc, ERASE);
240 	saved_for_arrow=arc->for_arrow;
241 	if (saved_back_arrow && saved_back_arrow != arc->back_arrow)
242 	    free((char *) saved_back_arrow);
243 	saved_back_arrow = NULL;
244 	arc->for_arrow = NULL;
245 	redisplay_arc(arc);
246     } else
247 	return;
248     clean_up();
249     set_last_arcpointnum(point_num);
250     set_latestarc(arc);
251     set_action_object(F_DELETE_ARROW_HEAD, O_ARC);
252     set_modifiedflag();
253 }
254 
255 void
delete_splinearrow(F_spline * spline,F_point * prev_point,F_point * selected_point)256 delete_splinearrow(F_spline *spline, F_point *prev_point, F_point *selected_point)
257 {
258     if (closed_spline(spline))
259 	return;
260     if (prev_point == NULL) {	/* selected_point is the first point */
261 	if (!spline->back_arrow)
262 	    return;
263 	draw_spline(spline, ERASE);
264 	saved_back_arrow=spline->back_arrow;
265 	if (saved_for_arrow && saved_for_arrow != spline->for_arrow)
266 	    free((char *) saved_for_arrow);
267 	saved_for_arrow = NULL;
268 	spline->back_arrow = NULL;
269 	redisplay_spline(spline);
270     } else if (selected_point->next == NULL) {	/* forward arrow */
271 	if (!spline->for_arrow)
272 	    return;
273 	draw_spline(spline, ERASE);
274 	saved_for_arrow=spline->for_arrow;
275 	if (saved_back_arrow && saved_back_arrow != spline->back_arrow)
276 	    free((char *) saved_back_arrow);
277 	saved_back_arrow = NULL;
278 	spline->for_arrow = NULL;
279 	redisplay_spline(spline);
280     } else
281 	return;
282     clean_up();
283     set_last_prevpoint(prev_point);
284     set_last_selectedpoint(selected_point);
285     set_latestspline(spline);
286     set_action_object(F_DELETE_ARROW_HEAD, O_SPLINE);
287     set_modifiedflag();
288 }
289 
290 
291 
292 
293 
294