missing NULL terminator in set_config_x
[geda-gaf.git] / gschem / src / x_stroke.c
blobb75eb19089d87794723d2caa51e13c1d4f1b3aa7
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>
22 #include "gschem.h"
24 #include <stroke.h>
27 * <B>stroke_points</B> is an array of points for the stroke
28 * footprints. The points of the stroke are displayed over the display
29 * area of the main window. They have to be erased when the stroke is
30 * translated and the sequence evaluated.
32 * Its size will never exceed <B>STROKE_MAX_POINTS</B> (the limit in
33 * number of points of a stroke provided by libstroke).
35 typedef struct {
36 gint x, y;
37 } StrokePoint;
39 static GArray *stroke_points = NULL;
42 /*! \brief Initializes the stroke interface.
43 * \par Function Description
44 * This is the initialization function for the stroke interface. It
45 * initializes the libstroke library and prepare an array of points
46 * for the mouse footprints.
48 * This function has to be called only once at application
49 * initialization before any use of the stroke interface.
51 void
52 x_stroke_init (void)
54 g_return_if_fail (stroke_points == NULL);
56 stroke_init ();
58 stroke_points = g_array_new (FALSE,
59 FALSE,
60 sizeof (StrokePoint));
63 /*! \brief Frees memory of the stroke interface.
64 * \par Function Description
65 * This function frees the memory used for the mouse footprint
66 * points. It terminates the use of the stroke interface.
68 void
69 x_stroke_free (void)
71 g_return_if_fail (stroke_points != NULL);
73 g_array_free (stroke_points, TRUE);
74 stroke_points = NULL;
77 /*! \brief Records a new point for the stroke.
78 * \par Function Description
79 * This function adds the point (<B>x</B>,<B>y</B>) as a new point in
80 * the stroke.
82 * The footprint is updated and the new point is drawn on the drawing area.
84 * \param [in] w_current The GschemToplevel object.
85 * \param [in] x The X coord of the new point.
86 * \param [in] Y The X coord of the new point.
88 void
89 x_stroke_record (GschemToplevel *w_current, gint x, gint y)
91 cairo_matrix_t user_to_device_matrix;
92 double x0, y0, x1, y1;
93 GschemPageView *view = gschem_toplevel_get_current_page_view (w_current);
94 g_return_if_fail (view != NULL);
95 GschemPageGeometry *geometry = gschem_page_view_get_page_geometry (view);
96 g_return_if_fail (geometry != NULL);
98 g_assert (stroke_points != NULL);
100 stroke_record (x, y);
102 if (stroke_points->len < STROKE_MAX_POINTS) {
103 StrokePoint point = { x, y };
105 g_array_append_val (stroke_points, point);
107 if (stroke_points->len == 1)
108 return;
110 StrokePoint *last_point = &g_array_index (stroke_points, StrokePoint,
111 stroke_points->len - 2);
113 cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (GTK_WIDGET(view)));
114 COLOR *color = x_color_lookup (STROKE_COLOR);
115 cairo_set_source_rgba (cr,
116 color->r / 255.0,
117 color->g / 255.0,
118 color->b / 255.0,
119 color->a / 255.0);
121 cairo_set_matrix (cr, gschem_page_geometry_get_world_to_screen_matrix (geometry));
122 x0 = last_point->x;
123 y0 = last_point->y;
124 x1 = x;
125 y1 = y;
126 cairo_device_to_user (cr, &x0, &y0);
127 cairo_device_to_user (cr, &x1, &y1);
128 cairo_get_matrix (cr, &user_to_device_matrix);
129 cairo_save (cr);
130 cairo_identity_matrix (cr);
132 cairo_matrix_transform_point (&user_to_device_matrix, &x0, &y0);
133 cairo_matrix_transform_point (&user_to_device_matrix, &x1, &y1);
135 cairo_move_to (cr, x0, y0);
136 cairo_line_to (cr, x1, y1);
137 cairo_stroke (cr);
138 cairo_restore (cr);
139 cairo_destroy (cr);
144 /*! \brief Evaluates the stroke.
145 * \par Function Description
146 * This function transforms the stroke input so far in an action.
148 * It makes use of the guile procedure <B>eval-stroke</B> to evaluate
149 * the stroke sequence into a possible action. The mouse footprint is
150 * erased in this function.
152 * It returns 1 if the stroke has been successfully evaluated as an
153 * action. It returns 0 if libstroke failed to transform the stroke
154 * or there is no action attached to the stroke.
156 * \param [in] w_current The GschemToplevel object.
157 * \returns 1 on success, 0 otherwise.
159 gint
160 x_stroke_translate_and_execute (GschemToplevel *w_current)
162 gchar sequence[STROKE_MAX_SEQUENCE];
163 StrokePoint *point;
164 int min_x, min_y, max_x, max_y;
165 gint i;
167 g_assert (stroke_points != NULL);
169 if (stroke_points->len == 0)
170 return 0;
172 point = &g_array_index (stroke_points, StrokePoint, 0);
173 min_x = max_x = point->x;
174 min_y = max_y = point->y;
176 for (i = 1; i < stroke_points->len; i++) {
177 point = &g_array_index (stroke_points, StrokePoint, i);
178 min_x = min (min_x, point->x);
179 min_y = min (min_y, point->y);
180 max_x = max (max_x, point->x);
181 max_y = max (max_y, point->y);
184 o_invalidate_rect (w_current, min_x, min_y, max_x + 1, max_y + 1);
186 /* resets length of array */
187 stroke_points->len = 0;
189 /* try evaluating stroke */
190 if (stroke_trans ((char*)&sequence)) {
191 gchar *guile_string =
192 g_strdup_printf("(eval-stroke \"%s\")", sequence);
193 SCM ret;
195 scm_dynwind_begin (0);
196 scm_dynwind_unwind_handler (g_free, guile_string, SCM_F_WIND_EXPLICITLY);
197 ret = g_scm_c_eval_string_protected (guile_string);
198 scm_dynwind_end ();
200 return (SCM_NFALSEP (ret));
203 return 0;