Updated copyright text/header in most source files.
[geda-gaf.git] / gschem / src / o_find.c
blobe2e99930610a534d88496aeae7922555aeb6d50b
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2010 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA
20 #include <config.h>
22 #include <math.h>
23 #include <stdio.h>
25 #include "gschem.h"
27 #ifdef HAVE_LIBDMALLOC
28 #include <dmalloc.h>
29 #endif
32 /*! \brief Tests a if a given OBJECT was hit at a given set of coordinates
34 * \par Function Description
35 * Tests a if a given OBJECT was hit at a given set of coordinates. If so,
36 * processes selection changes as appropriate for the object and passed
37 * flag. Saves a pointer to the found object so future find operations
38 * resume after this object.
40 * \param [in] w_current The GSCHEM_TOPLEVEL object.
41 * \param [in] object The OBJECT being hit-tested.
42 * \param [in] w_x The X coordinate to test (in world coords).
43 * \param [in] w_y The Y coordinate to test (in world coords).
44 * \param [in] w_slack The slack applied to the hit-test.
45 * \param [in] change_selection Whether to select the found object or not.
46 * \returns TRUE if the OBJECT was hit, otherwise FALSE.
48 static gboolean find_single_object (GSCHEM_TOPLEVEL *w_current, OBJECT *object,
49 int w_x, int w_y, int w_slack,
50 int change_selection)
52 TOPLEVEL *toplevel = w_current->toplevel;
53 if (object->sel_func != NULL &&
54 (object->visibility == VISIBLE || toplevel->show_hidden_text) &&
55 inside_region (object->w_left - w_slack, object->w_top - w_slack,
56 object->w_right + w_slack, object->w_bottom + w_slack,
57 w_x, w_y) &&
58 o_shortest_distance (object, w_x, w_y) < w_slack) {
59 if (change_selection) {
60 /* FIXME: should this be moved to o_select_object()? (Werner) */
61 if (object->type == OBJ_NET && w_current->net_selection_mode) {
62 o_select_connected_nets (w_current, object);
63 } else {
64 (*object->sel_func) (w_current, object, SINGLE, 0); /* 0 is count */
67 toplevel->page_current->object_lastplace = object;
68 i_update_menus (w_current);
69 return TRUE;
71 return FALSE;
75 /*! \brief Find an OBJECT at a given set of coordinates
77 * \par Function Description
78 * Tests for OBJECTS hit at a given set of coordinates. If
79 * change_selection is TRUE, it updates the page's selection.
81 * Find operations resume searching after the last object which was
82 * found, so multiple find operations at the same point will cycle
83 * through any objects on top of each other at this location.
85 * \param [in] w_current The GSCHEM_TOPLEVEL object.
86 * \param [in] object The OBJECT being hit-tested.
87 * \param [in] w_x The X coordinate to test (in world coords).
88 * \param [in] w_y The Y coordinate to test (in world coords).
89 * \param [in] change_selection Whether to select the found object or not.
90 * \returns TRUE if the object was hit at the given coordinates,
91 * otherwise FALSE.
93 gboolean o_find_object (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y,
94 gboolean change_selection)
96 TOPLEVEL *toplevel = w_current->toplevel;
97 int w_slack;
98 const GList *iter = NULL;
100 w_slack = WORLDabs (w_current, w_current->select_slack_pixels);
102 /* Decide whether to iterate over all object or start at the last
103 found object. If there is more than one object below the
104 (w_x/w_y) position, this will select the next object below the
105 position point. You can change the selected object by clicking
106 at the same place multiple times. */
107 if (toplevel->page_current->object_lastplace != NULL) {
108 /* NB: g_list_find doesn't declare its input const, so we cast */
109 iter = g_list_find ((GList *)s_page_objects (toplevel->page_current),
110 toplevel->page_current->object_lastplace);
111 iter = g_list_next (iter);
114 /* do first search (if we found any objects after the last found object) */
115 while (iter != NULL) {
116 OBJECT *o_current = iter->data;
117 if (find_single_object (w_current, o_current,
118 w_x, w_y, w_slack, change_selection)) {
119 return TRUE;
121 iter = g_list_next (iter);
124 /* now search from the beginning up until the object_lastplace */
125 for (iter = s_page_objects (toplevel->page_current);
126 iter != NULL; iter = g_list_next (iter)) {
127 OBJECT *o_current = iter->data;
128 if (find_single_object (w_current, o_current,
129 w_x, w_y, w_slack, change_selection)) {
130 return TRUE;
132 /* break once we've inspected up to where we started the first loop */
133 if (o_current == toplevel->page_current->object_lastplace)
134 break;
137 /* didn't find anything.... reset lastplace */
138 toplevel->page_current->object_lastplace = NULL;
140 /* deselect everything only if shift key isn't pressed and
141 the caller allows it */
142 if (change_selection && (!w_current->SHIFTKEY)) {
143 o_select_unselect_all (w_current);
146 i_update_menus(w_current);
147 return FALSE;
150 /*! \todo Finish function documentation!!!
151 * \brief
152 * \par Function Description
155 gboolean o_find_selected_object(GSCHEM_TOPLEVEL *w_current,
156 int w_x, int w_y)
158 TOPLEVEL *toplevel = w_current->toplevel;
159 OBJECT *o_current=NULL;
160 GList *s_current;
161 int w_slack;
163 w_slack = WORLDabs (w_current, w_current->select_slack_pixels);
165 s_current = geda_list_get_glist( toplevel->page_current->selection_list );
166 /* do first search */
167 while (s_current != NULL) {
168 o_current = (OBJECT *) s_current->data;
169 if (inside_region(o_current->w_left - w_slack, o_current->w_top - w_slack,
170 o_current->w_right + w_slack, o_current->w_bottom + w_slack,
171 w_x, w_y)) {
173 #if DEBUG
174 printf("o_find_selected_object:\n");
175 printf("Object bounds:\n\tL: %i\tR: %i\n\tT: %i\tB: %i.\n",
176 o_current->w_left, o_current->w_right, o_current->w_top, o_current->w_bottom);
177 printf("Screen pointer at: (%i,%i)\n", screen_x, screen_y);
178 #endif
179 if (o_current->sel_func != NULL &&
180 (o_current->visibility == VISIBLE || toplevel->show_hidden_text)) {
181 return TRUE;
185 s_current = g_list_next(s_current);
188 return (FALSE);