missing NULL terminator in set_config_x
[geda-gaf.git] / gschem / src / o_arc.c
blob19d83a0a5bb8585e02bd3c0e6412694faac676a3
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2020 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include <config.h>
21 #include <stdio.h>
22 #include <math.h>
24 #include "gschem.h"
26 /*! \todo Finish function documentation!!!
27 * \brief
28 * \par Function Description
31 void o_arc_invalidate_rubber (GschemToplevel *w_current)
33 g_return_if_fail (w_current != NULL);
35 GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current);
37 /* FIXME: This isn't a tight bounding box */
39 gschem_page_view_invalidate_world_rect (page_view,
40 w_current->first_wx - w_current->distance,
41 w_current->first_wy - w_current->distance,
42 w_current->first_wx + w_current->distance,
43 w_current->first_wy + w_current->distance);
46 /*! \brief Start process to input a new arc.
47 * \par Function Description
48 * This function starts the process to input a new arc. Parameters for
49 * this arc are put into/extracted from the <B>w_current</B> toplevel structure.
50 * <B>w_x</B> and <B>w_y</B> are current coordinates of the pointer in screen unit.
52 * First step of the arc input is to set the radius of the arc. The center
53 * of the arc is kept in (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>).
54 * The radius of the arc is in <B>w_current->distance</B>.
56 * \param [in] w_current The GschemToplevel object.
57 * \param [in] w_x Current x coordinate of pointer in world units.
58 * \param [in] w_y Current y coordinate of pointer in world units.
60 void o_arc_start(GschemToplevel *w_current, int w_x, int w_y)
62 i_action_start (w_current);
64 /* set the center of the arc */
65 w_current->first_wx = w_x;
66 w_current->first_wy = w_y;
68 /* set the radius */
69 w_current->distance = 0;
71 /* set the start and end angles */
72 w_current->second_wx = w_current->second_wy = 0;
74 /* start the rubberbanding process of the radius */
75 o_arc_invalidate_rubber (w_current);
76 w_current->rubber_visible = 1;
79 /*! \brief End the input of an arc.
80 * \par Function Description
81 * This function ends the input of the radius of the arc.
82 * The (<B>w_x</B>,<B>w_y</B>) point is taken as the other end of the radius segment.
83 * The distance between this point and the center is the radius of the arc.
84 * <B>w_x</B> and <B>w_y</B> are in world coords.
86 * At the end of this function, the center of the arc is at
87 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>) and its radius is
88 * <B>w_current->distance</B>.
90 * The two angles needs to be input to fully define the arc.
92 * \param [in] w_current The GschemToplevel object.
93 * \param [in] w_x (unused)
94 * \param [in] w_y (unused)
96 void o_arc_end1(GschemToplevel *w_current, int w_x, int w_y)
98 g_assert( w_current->inside_action != 0 );
100 /* erases the previous temporary radius segment */
101 /* o_arc_invalidate_rubber (w_current); */
102 w_current->rubber_visible = 0;
104 /* ack! zero length radius */
105 if (w_current->distance != 0) {
107 #if DEBUG
108 printf("DIST: %d\n", w_current->distance);
109 #endif
111 /* open a dialog to input the start and end angle */
112 arc_angle_dialog(w_current, NULL);
115 i_action_stop (w_current);
118 /*! \brief Ends the process of arc input.
119 * \par Function Description
120 * The #o_arc_end4() function ends the process of the input of an arc.
121 * <B>start_angle</B> and <B>sweep_angle</B> are the start and sweep angle of the
122 * arc in degrees. The partial internal representation of the arc, i.e.
123 * the center and the radius of the arc, are converted in world units.
124 * A new object is created and linked to the object list.
126 * \param [in] w_current The GschemToplevel object.
127 * \param [in] radius Radius of the arc
128 * \param [in] start_angle Start of angle in degrees.
129 * \param [in] sweep_angle Angle sweep in degrees.
131 void o_arc_end4(GschemToplevel *w_current, int radius,
132 int start_angle, int sweep_angle)
134 GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current);
135 g_return_if_fail (page_view != NULL);
137 PAGE *page = gschem_page_view_get_page (page_view);
138 g_return_if_fail (page != NULL);
140 TOPLEVEL *toplevel = page->toplevel;
141 g_return_if_fail (toplevel != NULL);
143 OBJECT *new_obj;
145 /* create, initialize and link the new arc object */
146 new_obj = o_arc_new (toplevel, GRAPHIC_COLOR,
147 w_current->first_wx, w_current->first_wy,
148 radius, start_angle, sweep_angle);
149 s_page_append (toplevel, page, new_obj);
151 w_current->first_wx = -1;
152 w_current->first_wy = -1;
153 w_current->distance = 0;
155 /* Call add-objects-hook */
156 g_run_hook_object (w_current, "%add-objects-hook", new_obj);
158 gschem_toplevel_page_content_changed (w_current, page);
159 o_undo_savestate (w_current, page, UNDO_ALL, _("Arc"));
162 /*! \brief Draw an arc using one angle modification.
163 * \par Function Description
164 * This function draws an arc according to its internal representation
165 * and allows the modification of one of its angle. The start or end
166 * angle of the arc is updated according to <B>whichone</B> with the angle
167 * that the current pointer and the arc center are making with the horizontal.
169 * The previous temporary arc is erased, the angle is then computed
170 * and updated and finally a new temporary arc with the new angle is drawn.
172 * The arc is internally described by :
173 * <DL>
174 * <DT>*</DT><DD>(<B>w_current->first_wx</B>,<B>w_current->first_wy</B>) as
175 * its center.
176 * <DT>*</DT><DD><B>w_current->distance</B> as its radius.
177 * <DT>*</DT><DD><B>w_current->second_wx</B> and <B>w_current->second_wx</B> as its
178 * start and end angle respectively.
179 * </DL>
181 * \param [in] w_current The GschemToplevel object.
182 * \param [in] w_x Current x coordinate of pointer in world units.
183 * \param [in] w_y Current y coordinate of pointer in world units.
184 * \param [in] whichone Which angle to change.
186 * <B>whichone</B> can have one of the following values:
187 * <DL>
188 * <DT>ARC_RADIUS</DT>
189 * <DD>at the center of the arc. This grip is used to modify
190 * the radius of the arc.
191 * <DT>ARC_START_ANGLE</DT>
192 * <DD>at one end of the arc. It corresponds to the starting
193 * angle of the arc.
194 * <DT>ARC_SWEEP_ANGLE</DT>
195 * <DD>at the other end of the arc. It corresponds to the
196 * ending angle of the arc.
197 * </DL>
199 void o_arc_motion (GschemToplevel *w_current, int w_x, int w_y, int whichone)
201 int diff_x, diff_y, angle_deg;
203 g_assert (w_current->inside_action != 0);
205 /* erase the previous temporary arc */
206 if (w_current->rubber_visible)
207 o_arc_invalidate_rubber (w_current);
209 if(whichone == ARC_RADIUS) {
211 * The radius is taken as the biggest distance on the x and y
212 * axis between the center of the arc and the mouse position.
214 diff_x = abs(w_current->first_wx - snap_grid (w_current, w_x));
215 diff_y = abs(w_current->first_wy - snap_grid (w_current, w_y));
216 w_current->distance = max(diff_x, diff_y);
218 else if((whichone == ARC_START_ANGLE) || (whichone == ARC_SWEEP_ANGLE)) {
219 /* compute the angle */
220 diff_x = w_x - w_current->first_wx;
221 diff_y = w_y - w_current->first_wy;
222 angle_deg = atan2 (diff_y, diff_x) * 180 / M_PI;
224 /* set the start or end angle with this angle */
225 switch(whichone) {
226 case ARC_START_ANGLE:
227 w_current->second_wx = (angle_deg + 360) % 360;
228 break;
230 case ARC_SWEEP_ANGLE:
231 w_current->second_wy = (((angle_deg + 360) % 360) -
232 w_current->second_wx + 360) % 360;
233 if (w_current->which_object->arc->sweep_angle < 0)
234 w_current->second_wy = w_current->second_wy - 360;
235 if (w_current->second_wy == 0)
236 w_current->second_wy = 360;
237 break;
240 * No default required - one of above two branches
241 * *must* be taken - Coverity ID 201571
247 /* draw the new temporary arc */
248 o_arc_invalidate_rubber (w_current);
249 w_current->rubber_visible = 1;
252 /*! \brief Draw arc from GschemToplevel object.
253 * \par Function Description
254 * This function draws the arc from the variables in the GschemToplevel
255 * structure <B>*w_current</B>.
256 * The center of the arc is at (<B>w_current->first_wx</B>,
257 * <B>w_current->first_wy</B>), its radius equal to <B>w_current->distance</B>,
258 * and the start and end angle are given by <B>w_current->second_wx</B> and
259 * <B>w_current->second_wy</B>.
261 * \param [in] w_current The GschemToplevel object.
263 void o_arc_draw_rubber (GschemToplevel *w_current, EdaRenderer *renderer)
265 double rad_angle;
266 int rdx, rdy;
267 double wwidth = 0;
268 cairo_t *cr = eda_renderer_get_cairo_context (renderer);
269 GArray *color_map = eda_renderer_get_color_map (renderer);
270 int flags = eda_renderer_get_cairo_flags (renderer);
272 eda_cairo_arc (cr, flags, wwidth,
273 w_current->first_wx, w_current->first_wy,
274 w_current->distance,
275 w_current->second_wx, w_current->second_wy);
277 eda_cairo_set_source_color (cr, SELECT_COLOR, color_map);
279 /* draw the radius line */
280 rad_angle = ((double) w_current->second_wx) * M_PI / 180;
281 rdx = (double) w_current->distance * cos (rad_angle);
282 rdy = (double) w_current->distance * sin (rad_angle);
284 eda_cairo_line (cr, flags, END_NONE, wwidth,
285 w_current->first_wx, w_current->first_wy,
286 w_current->first_wx + rdx, w_current->first_wy + rdy);
288 eda_cairo_stroke (cr, flags, TYPE_SOLID, END_NONE, wwidth, -1, -1);