libgeda: Remove some exit() calls and assertions.
[geda-gaf/peter-b.git] / libgeda / src / o_basic.c
blobbbbd47761607943327eb7723c4afdd225bc3e372
1 /* gEDA - GPL Electronic Design Automation
2 * libgeda - gEDA's library
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 /*! \file o_basic.c
22 * \brief functions for the basic object type
24 * This file contains the code used to handle OBJECTs (st_object).
25 * The object is the basic type of all elements stored in schematic
26 * and symbol files.
28 * The object be extended to become concrete objects like a line,
29 * a pin, text, a circle or a picture. These extentions are substructures
30 * in the object struct.
31 * The subobjects are picture (st_picture), path (st_path), arcs (st_arc),
32 * a line (st_line), box (st_box), circle (st_circle), text (st_text) and
33 * a complex type (st_complex).
35 * Pins, nets and busses are just a kind of a line.
37 * The complex object can carry many primary objects. If the complex
38 * object is a symbol, then the complex symbol contains all the pins,
39 * the text and the graphics.
41 * \image html o_object_relations.png
42 * \image latex o_object_relations.pdf "object relations" width=14cm
45 #include <config.h>
47 #include <stdio.h>
49 /* instrumentation code */
50 #if 0
51 #include <sys/time.h>
52 #include <unistd.h>
53 #endif
55 #include "libgeda_priv.h"
57 #ifdef HAVE_LIBDMALLOC
58 #include <dmalloc.h>
59 #endif
62 /*! \brief Check if point is inside a region
63 * \par Function Description
64 * This function takes a rectangular region and a point. It will check
65 * if the point is located in the region or not.
67 * \param [in] xmin Smaller x coordinate of the region.
68 * \param [in] ymin Smaller y coordinate of the region.
69 * \param [in] xmax Larger x coordinate of the region.
70 * \param [in] ymax Larger y coordinate of the region.
71 * \param [in] x x coordinate of the point to check.
72 * \param [in] y y coordinate of the point to check.
73 * \return 1 if the point is inside the region, 0 otherwise.
75 int inside_region(int xmin, int ymin, int xmax, int ymax, int x, int y)
77 return ((x >= xmin && x <= xmax && y >= ymin && y <= ymax) ? 1 : 0);
80 /*! \brief Recalculate position of the given object.
81 * \par Function Description
82 * This function will take an object and recalculate its
83 * position on the screen.
85 * \param [in] toplevel The TOPLEVEL object.
86 * \param [in,out] o_current OBJECT to recalculate.
89 void o_recalc_single_object(TOPLEVEL *toplevel, OBJECT *o_current)
91 if (o_current != NULL) {
92 switch(o_current->type) {
94 case(OBJ_LINE):
95 o_line_recalc(toplevel, o_current);
96 break;
98 case(OBJ_NET):
99 o_net_recalc(toplevel, o_current);
100 break;
102 case(OBJ_BUS):
103 o_bus_recalc(toplevel, o_current);
104 break;
106 case(OBJ_BOX):
107 o_box_recalc(toplevel, o_current);
108 break;
110 case(OBJ_PATH):
111 o_path_recalc(toplevel, o_current);
112 break;
114 case(OBJ_PICTURE):
115 o_picture_recalc(toplevel, o_current);
116 break;
118 case(OBJ_CIRCLE):
119 o_circle_recalc(toplevel, o_current);
120 break;
122 case(OBJ_COMPLEX):
123 case(OBJ_PLACEHOLDER):
124 o_complex_recalc(toplevel, o_current);
125 break;
127 case(OBJ_PIN):
128 o_pin_recalc(toplevel, o_current);
129 break;
131 case(OBJ_ARC):
132 o_arc_recalc(toplevel, o_current);
133 break;
135 case(OBJ_TEXT):
136 o_text_recalc(toplevel, o_current);
137 break;
143 /*! \brief Recalculate position of a list (GList) of objects.
144 * \par Function Description
145 * This function will take a list (GList) of objects and recalculate their
146 * positions on the screen.
148 * \param [in] toplevel The TOPLEVEL object.
149 * \param [in,out] object_glist OBJECT list to recalculate.
152 void
153 o_recalc_object_glist(TOPLEVEL *toplevel, GList *object_glist)
155 GList *list = object_glist;
156 OBJECT *o_current;
158 while (list != NULL) {
159 o_current = (OBJECT *) list->data;
160 o_recalc_single_object(toplevel, o_current);
161 list = g_list_next(list);
166 /*! \brief Set an #OBJECT's line options.
167 * \par Function Description
168 * This function allows a line's end, type, width, length and space to be set.
169 * See #OBJECT_END and #OBJECT_TYPE for information on valid
170 * object end and type values.
172 * \param [in] toplevel The TOPLEVEL object.
173 * \param [in,out] o_current OBJECT to set line options on.
174 * \param [in] end An OBJECT_END.
175 * \param [in] type An OBJECT_TYPE.
176 * \param [in] width Line width.
177 * \param [in] length Line length.
178 * \param [in] space Spacing between dashes/dots. Cannot be negative.
180 * \todo Make space an unsigned int and check for a max value instead.
181 * If a max value is not required, then it would simplify the code.
183 void o_set_line_options(TOPLEVEL *toplevel, OBJECT *o_current,
184 OBJECT_END end, OBJECT_TYPE type,
185 int width, int length, int space)
187 if(o_current == NULL) {
188 return;
191 /* do some error checking / correcting */
192 switch(type) {
193 case(TYPE_DOTTED):
194 if (space < 1) {
195 space = 100;
196 s_log_message (_("Invalid space specified, setting to 100\n"));
198 break;
199 case(TYPE_DASHED):
200 case(TYPE_CENTER):
201 case(TYPE_PHANTOM):
202 if (length < 1) {
203 length = 100;
204 s_log_message (_("Invalid length specified, setting to 100\n"));
206 if (space < 1) {
207 space = 100;
208 s_log_message (_("Invalid space specified, setting to 100\n"));
210 break;
211 default:
213 break;
216 o_emit_pre_change_notify (toplevel, o_current);
218 o_current->line_width = width;
219 o_current->line_end = end;
220 o_current->line_type = type;
222 o_current->line_length = length;
223 o_current->line_space = space;
225 /* Recalculate the object's bounding box */
226 o_recalc_single_object( toplevel, o_current );
227 o_emit_change_notify (toplevel, o_current);
231 /*! \brief get #OBJECT's line properties.
232 * \par Function Description
233 * This function get's the #OBJECT's line options.
234 * See #OBJECT_END and #OBJECT_TYPE for information on valid
235 * object end and type values.
237 * \param [in] object OBJECT to read the properties
238 * \param [out] end An OBJECT_END.
239 * \param [out] type An OBJECT_TYPE.
240 * \param [out] width Line width.
241 * \param [out] length Line length.
242 * \param [out] space Spacing between dashes/dots.
243 * \return TRUE on succes, FALSE otherwise
246 gboolean o_get_line_options(OBJECT *object,
247 OBJECT_END *end, OBJECT_TYPE *type,
248 int *width, int *length, int *space)
250 if (object->type != OBJ_LINE
251 && object->type != OBJ_ARC
252 && object->type != OBJ_BOX
253 && object->type != OBJ_CIRCLE
254 && object->type != OBJ_PATH)
255 return FALSE;
257 *end = object->line_end;
258 *type = object->line_type;
259 *width = object->line_width;
260 *length = object->line_length;
261 *space = object->line_space;
263 return TRUE;
266 /*! \brief Set #OBJECT's fill options.
267 * \par Function Description
268 * This function allows an #OBJECT's fill options to be configured.
269 * See #OBJECT_FILLING for information on valid fill types.
271 * \param [in] toplevel The TOPLEVEL object.
272 * \param [in,out] o_current OBJECT to be updated.
273 * \param [in] type OBJECT_FILLING type.
274 * \param [in] width fill width.
275 * \param [in] pitch1 cross hatch line distance
276 * \param [in] angle1 cross hatch angle
277 * \param [in] pitch2 cross hatch line distance
278 * \param [in] angle2 cross hatch angle
281 void o_set_fill_options(TOPLEVEL *toplevel, OBJECT *o_current,
282 OBJECT_FILLING type, int width,
283 int pitch1, int angle1,
284 int pitch2, int angle2)
286 if(o_current == NULL) {
287 return;
290 o_emit_pre_change_notify (toplevel, o_current);
292 o_current->fill_type = type;
293 o_current->fill_width = width;
295 o_current->fill_pitch1 = pitch1;
296 o_current->fill_angle1 = angle1;
298 o_current->fill_pitch2 = pitch2;
299 o_current->fill_angle2 = angle2;
301 o_emit_change_notify (toplevel, o_current);
304 /*! \brief get #OBJECT's fill properties.
305 * \par Function Description
306 * This function get's the #OBJECT's fill options.
307 * See #OBJECT_FILLING for information on valid fill types.
309 * \param [in] object OBJECT to read the properties
310 * \param [out] type OBJECT_FILLING type
311 * \param [out] width fill width.
312 * \param [out] pitch1 cross hatch line distance
313 * \param [out] angle1 cross hatch angle
314 * \param [out] pitch2 cross hatch line distance
315 * \param [out] angle2 cross hatch angle
316 * \return TRUE on succes, FALSE otherwise
319 gboolean o_get_fill_options(OBJECT *object,
320 OBJECT_FILLING *type, int *width,
321 int *pitch1, int *angle1,
322 int *pitch2, int *angle2)
324 if (object->type != OBJ_BOX
325 && object->type != OBJ_CIRCLE
326 && object->type != OBJ_PATH)
327 return FALSE;
329 *type = object->fill_type;
330 *width = object->fill_width;
331 *pitch1 = object->fill_pitch1;
332 *angle1 = object->fill_angle1;
333 *pitch2 = object->fill_pitch2;
334 *angle2 = object->fill_angle2;
336 return TRUE;
339 /*! \brief get the base position of an object
340 * \par Function Description
341 * This function gets the position of an object in world coordinates.
343 * \param [in] toplevel The toplevel environment.
344 * \param [out] x pointer to the x-position
345 * \param [out] y pointer to the y-position
346 * \param [in] object The object to get the position.
347 * \return TRUE if successfully determined the position, FALSE otherwise
349 gboolean o_get_position (TOPLEVEL *toplevel, gint *x, gint *y, OBJECT *object)
351 gboolean (*func) (TOPLEVEL*, int*, int*, OBJECT*) = NULL;
353 switch (object->type) {
354 case OBJ_LINE: func = o_line_get_position; break;
355 case OBJ_NET: func = o_net_get_position; break;
356 case OBJ_BUS: func = o_bus_get_position; break;
357 case OBJ_BOX: func = o_box_get_position; break;
358 case OBJ_PICTURE: func = o_picture_get_position; break;
359 case OBJ_CIRCLE: func = o_circle_get_position; break;
360 case OBJ_PLACEHOLDER:
361 case OBJ_COMPLEX: func = o_complex_get_position; break;
362 case OBJ_TEXT: func = o_text_get_position; break;
363 case OBJ_PATH: func = o_path_get_position; break;
364 case OBJ_PIN: func = o_pin_get_position; break;
365 case OBJ_ARC: func = o_arc_get_position; break;
366 default:
367 g_critical ("o_get_position: object %p has bad type '%c'\n",
368 object, object->type);
371 if (func != NULL) {
372 return (*func) (toplevel, x, y, object);
374 return FALSE;
378 /*! \brief Translates an object in world coordinates
379 * \par Function Description
380 * This function translates the object <B>object</B> by
381 * <B>dx</B> and <B>dy</B>.
383 * \param [in] toplevel The toplevel environment.
384 * \param [in] dx Amount to horizontally translate object
385 * \param [in] dy Amount to vertically translate object
386 * \param [in] object The object to translate.
388 void o_translate_world (TOPLEVEL *toplevel, gint dx, gint dy, OBJECT *object)
390 void (*func) (TOPLEVEL*, int, int, OBJECT*) = NULL;
392 switch (object->type) {
393 case OBJ_LINE: func = o_line_translate_world; break;
394 case OBJ_NET: func = o_net_translate_world; break;
395 case OBJ_BUS: func = o_bus_translate_world; break;
396 case OBJ_BOX: func = o_box_translate_world; break;
397 case OBJ_PICTURE: func = o_picture_translate_world; break;
398 case OBJ_CIRCLE: func = o_circle_translate_world; break;
399 case OBJ_PLACEHOLDER:
400 case OBJ_COMPLEX: func = o_complex_translate_world; break;
401 case OBJ_TEXT: func = o_text_translate_world; break;
402 case OBJ_PATH: func = o_path_translate_world; break;
403 case OBJ_PIN: func = o_pin_translate_world; break;
404 case OBJ_ARC: func = o_arc_translate_world; break;
405 default:
406 g_critical ("o_translate_world: object %p has bad type '%c'\n",
407 object, object->type);
410 if (func != NULL) {
411 (*func) (toplevel, dx, dy, object);
416 /*! \brief Rotates an object in world coordinates
417 * \par Function Description
418 * This function rotates the object <B>object</B> about the coordinates
419 * <B>world_centerx</B> and <B>world_centery</B>, by <B>angle</B>degrees.
421 * \param [in] toplevel The toplevel environment.
422 * \param [in] world_centerx X coordinate of rotation center (world coords)
423 * \param [in] world_centery Y coordinate of rotation center (world coords)
424 * \param [in] angle Angle of rotation (degrees)
425 * \param [in] object The object to rotate.
427 void o_rotate_world (TOPLEVEL *toplevel, int world_centerx, int world_centery, int angle, OBJECT *object)
429 void (*func) (TOPLEVEL*, int, int, int, OBJECT*) = NULL;
431 switch (object->type) {
432 case OBJ_LINE: func = o_line_rotate_world; break;
433 case OBJ_NET: func = o_net_rotate_world; break;
434 case OBJ_BUS: func = o_bus_rotate_world; break;
435 case OBJ_BOX: func = o_box_rotate_world; break;
436 case OBJ_PICTURE: func = o_picture_rotate_world; break;
437 case OBJ_CIRCLE: func = o_circle_rotate_world; break;
438 case OBJ_PLACEHOLDER:
439 case OBJ_COMPLEX: func = o_complex_rotate_world; break;
440 case OBJ_TEXT: func = o_text_rotate_world; break;
441 case OBJ_PATH: func = o_path_rotate_world; break;
442 case OBJ_PIN: func = o_pin_rotate_world; break;
443 case OBJ_ARC: func = o_arc_rotate_world; break;
444 default:
445 g_critical ("o_rotate_world: object %p has bad type '%c'\n",
446 object, object->type);
449 if (func != NULL) {
450 (*func) (toplevel, world_centerx, world_centery, angle, object);
455 /*! \brief Mirrors an object in world coordinates
456 * \par Function Description
457 * This function mirrors an object about the point
458 * (<B>world_centerx</B>,<B>world_centery</B>) in world units.
460 * \param [in] toplevel The TOPLEVEL object.
461 * \param [in] world_centerx Origin x coordinate in WORLD units.
462 * \param [in] world_centery Origin y coordinate in WORLD units.
463 * \param [in,out] object The OBJECT to mirror.
465 void o_mirror_world (TOPLEVEL *toplevel, int world_centerx, int world_centery, OBJECT *object)
467 void (*func) (TOPLEVEL*, int, int, OBJECT*) = NULL;
469 switch (object->type) {
470 case OBJ_LINE: func = o_line_mirror_world; break;
471 case OBJ_NET: func = o_net_mirror_world; break;
472 case OBJ_BUS: func = o_bus_mirror_world; break;
473 case OBJ_BOX: func = o_box_mirror_world; break;
474 case OBJ_PICTURE: func = o_picture_mirror_world; break;
475 case OBJ_CIRCLE: func = o_circle_mirror_world; break;
476 case OBJ_PLACEHOLDER:
477 case OBJ_COMPLEX: func = o_complex_mirror_world; break;
478 case OBJ_TEXT: func = o_text_mirror_world; break;
479 case OBJ_PATH: func = o_path_mirror_world; break;
480 case OBJ_PIN: func = o_pin_mirror_world; break;
481 case OBJ_ARC: func = o_arc_mirror_world; break;
482 default:
483 g_critical ("o_mirror_world: object %p has bad type '%c'\n",
484 object, object->type);
487 if (func != NULL) {
488 (*func) (toplevel, world_centerx, world_centery, object);
493 /*! \brief Calculates the distance between the given point and the closest
494 * point on the given object.
496 * \param [in] object The given object.
497 * \param [in] x The x coordinate of the given point.
498 * \param [in] y The y coordinate of the given point.
499 * \return The shortest distance from the object to the point. If the
500 * distance cannot be calculated, this function returns a really large
501 * number (G_MAXDOUBLE). If an error occurs, this function returns
502 * G_MAXDOUBLE.
504 double o_shortest_distance (OBJECT *object, int x, int y)
506 return o_shortest_distance_full (object, x, y, FALSE);
509 /*! \brief Calculates the distance between the given point and the closest
510 * point on the given object. Allows forcing objects to solid.
512 * \param [in] object The given object.
513 * \param [in] x The x coordinate of the given point.
514 * \param [in] y The y coordinate of the given point.
515 * \param [in] force_solid If true, force treating the object as solid.
516 * \return The shortest distance from the object to the point. If the
517 * distance cannot be calculated, this function returns a really large
518 * number (G_MAXDOUBLE). If an error occurs, this function returns
519 * G_MAXDOUBLE.
521 double o_shortest_distance_full (OBJECT *object, int x, int y, int force_solid)
523 double shortest_distance = G_MAXDOUBLE;
524 double (*func) (OBJECT *, int, int, int) = NULL;
526 g_return_val_if_fail (object != NULL, G_MAXDOUBLE);
528 switch(object->type) {
529 case OBJ_BUS:
530 case OBJ_NET:
531 case OBJ_PIN:
532 case OBJ_LINE: func = o_line_shortest_distance; break;
533 case OBJ_BOX: func = o_box_shortest_distance; break;
534 case OBJ_PICTURE: func = o_picture_shortest_distance; break;
535 case OBJ_CIRCLE: func = o_circle_shortest_distance; break;
536 case OBJ_PLACEHOLDER:
537 case OBJ_COMPLEX: func = o_complex_shortest_distance; break;
538 case OBJ_TEXT: func = o_text_shortest_distance; break;
539 case OBJ_PATH: func = o_path_shortest_distance; break;
540 case OBJ_ARC: func = o_arc_shortest_distance; break;
541 default:
542 g_critical ("o_shortest_distance: object %p has bad type '%c'\n",
543 object, object->type);
546 if (func != NULL) {
547 shortest_distance = (*func) (object, x, y, force_solid);
550 return shortest_distance;
553 /*! \brief Mark an OBJECT's cached bounds as invalid
554 * \par Function Description
555 * Recursively marks the cached bounds of the given OBJECT and its
556 * parents as having been invalidated and in need of an update. They
557 * will be recalculated next time the OBJECT's bounds are requested
558 * (e.g. via world_get_single_object_bounds() ).
559 * \param [in] toplevel
560 * \param [in] obj
562 * \todo Turn this into a macro?
564 void o_bounds_invalidate(TOPLEVEL *toplevel, OBJECT *obj)
566 do {
567 obj->w_bounds_valid = FALSE;
568 } while ((obj = obj->parent) != NULL);
572 /*! \brief Change the color of an object
574 * \par Function Description
575 * This function changes the color of an object.
577 * \param [in] toplevel The TOPLEVEL structure.
578 * \param [in] object The OBJECT to change color.
579 * \param [in] color The new color.
581 void o_set_color (TOPLEVEL *toplevel, OBJECT *object, int color)
583 g_return_if_fail (object != NULL);
585 object->color = color;
587 if (object->type == OBJ_COMPLEX ||
588 object->type == OBJ_PLACEHOLDER)
589 o_glist_set_color (toplevel, object->complex->prim_objs, color);
593 /*! \brief Get an object's parent PAGE.
595 * \par Function Description
596 * Returns the PAGE structure which owns \a object. If \a object is
597 * not currently associated with a PAGE, returns NULL. If \a object is
598 * part of a compound object, recurses upward.
600 * \param [in] toplevel The TOPLEVEL structure.
601 * \param [in] object The OBJECT for which to retrieve the parent PAGE.
602 * \return The PAGE which owns \a object or NULL.
604 * \sa s_page_append_object() s_page_append() s_page_remove()
606 PAGE *
607 o_get_page (TOPLEVEL *toplevel, OBJECT *object)
609 if (object->parent != NULL) {
610 return o_get_page (toplevel, object->parent);
612 return object->page;
615 /*! \brief Get an object's parent PAGE, or fall back to global current page.
617 * \par Function Description
618 * If set, returns the PAGE structure which owns \a object. If \a
619 * object does not have a parent page set, returns the global current
620 * page from \a toplevel. If the object parent page is inconsistent
621 * with the global current page, a critical-level error message is
622 * emitted.
624 * \warning This function is primarily intended to assist in the
625 * migration of code from using the TOPLEVEL current page to using the
626 * o_get_page(). It should not be used in new code.
628 * \deprecated Use o_get_page() in new code.
630 * \param [in] toplevel The TOPLEVEL structure.
631 * \param [in] object The OBJECT for which to retrieve the parent PAGE.
632 * \return The PAGE which owns \a object, the global current PAGE, or NULL.
634 PAGE *
635 o_get_page_compat (TOPLEVEL *toplevel, OBJECT *object) {
636 PAGE *page = o_get_page (toplevel, object);
637 if (page != toplevel->page_current) {
638 g_critical ("o_get_page_compat: OBJECT.page = %p, TOPLEVEL.page_current = %p",
639 page, toplevel->page_current);
640 return toplevel->page_current;
641 } else {
642 return page;
646 /*! \brief Get an object's containing complex object.
648 * \par Function Description
649 * If \a object is part of a complex #OBJECT, returns that
650 * #OBJECT. Otherwise, returns NULL.
652 * \param [in] toplevel The TOPLEVEL structure.
653 * \param [in] object The OBJECT for which to get the containing OBJECT.
654 * \return The complex OBJECT which owns \a object, or NULL.
656 OBJECT *
657 o_get_parent (TOPLEVEL *toplevel, OBJECT *object)
659 g_return_val_if_fail ((object != NULL), NULL);
661 if (object->parent != NULL) {
662 return object->parent;
664 return NULL;
667 /* Structure for each entry in a TOPLEVEL's list of registered change
668 * notification handlers */
669 struct change_notify_entry {
670 ChangeNotifyFunc pre_change_func;
671 ChangeNotifyFunc change_func;
672 void *user_data;
675 /*! \brief Add change notification handlers to a TOPLEVEL.
676 * \par Function Description
677 * Adds a set of change notification handlers to a #TOPLEVEL instance.
678 * \a pre_change_func will be called just before an object is
679 * modified, and \a change_func will be called just after an object is
680 * modified, with the affected object and the given \a user_data.
682 * \param toplevel #TOPLEVEL structure to add handlers to.
683 * \param pre_change_func Function to be called just before changes.
684 * \param change_func Function to be called just after changes.
685 * \param user_data User data to be passed to callback functions.
687 void
688 o_add_change_notify (TOPLEVEL *toplevel,
689 ChangeNotifyFunc pre_change_func,
690 ChangeNotifyFunc change_func,
691 void *user_data)
693 struct change_notify_entry *entry = g_new0 (struct change_notify_entry, 1);
694 entry->pre_change_func = pre_change_func;
695 entry->change_func = change_func;
696 entry->user_data = user_data;
697 toplevel->change_notify_funcs =
698 g_list_prepend (toplevel->change_notify_funcs, entry);
701 /*! \brief Remove change notification handlers from a TOPLEVEL.
702 * \par Function Description
703 * Removes a set of change notification handlers and their associated
704 * \a user_data from \a toplevel. If no registered set of handlers
705 * matches the given \a pre_change_func, \a change_func and \a
706 * user_data, does nothing.
708 * \see o_add_change_notify()
710 * \param toplevel #TOPLEVEL structure to remove handlers from.
711 * \param pre_change_func Function called just before changes.
712 * \param change_func Function called just after changes.
713 * \param user_data User data passed to callback functions.
715 void
716 o_remove_change_notify (TOPLEVEL *toplevel,
717 ChangeNotifyFunc pre_change_func,
718 ChangeNotifyFunc change_func,
719 void *user_data)
721 GList *iter;
722 for (iter = toplevel->change_notify_funcs;
723 iter != NULL; iter = g_list_next (iter)) {
725 struct change_notify_entry *entry =
726 (struct change_notify_entry *) iter->data;
728 if ((entry != NULL)
729 && (entry->pre_change_func == pre_change_func)
730 && (entry->change_func == change_func)
731 && (entry->user_data == user_data)) {
732 g_free (entry);
733 iter->data = NULL;
736 toplevel->change_notify_funcs =
737 g_list_remove_all (toplevel->change_notify_funcs, NULL);
740 /*! \brief Emit an object pre-change notification.
741 * \par Function Description
742 * Calls each pre-change callback function registered with #TOPLEVEL
743 * to notify listeners that \a object is about to be modified. All
744 * libgeda functions that modify #OBJECT structures should call this
745 * just before making a change to an #OBJECT.
747 * \param toplevel #TOPLEVEL structure to emit notifications from.
748 * \param object #OBJECT structure to emit notifications for.
750 void
751 o_emit_pre_change_notify (TOPLEVEL *toplevel, OBJECT *object)
753 GList *iter;
754 for (iter = toplevel->change_notify_funcs;
755 iter != NULL; iter = g_list_next (iter)) {
757 struct change_notify_entry *entry =
758 (struct change_notify_entry *) iter->data;
760 if ((entry != NULL) && (entry->pre_change_func != NULL)) {
761 entry->pre_change_func (entry->user_data, object);
766 /*! \brief Emit an object change notification.
767 * \par Function Description
768 * Calls each change callback function registered with #TOPLEVEL to
769 * notify listeners that \a object has just been modified. All
770 * libgeda functions that modify #OBJECT structures should call this
771 * just after making a change to an #OBJECT.
773 * \param toplevel #TOPLEVEL structure to emit notifications from.
774 * \param object #OBJECT structure to emit notifications for.
776 void
777 o_emit_change_notify (TOPLEVEL *toplevel, OBJECT *object)
779 GList *iter;
780 for (iter = toplevel->change_notify_funcs;
781 iter != NULL; iter = g_list_next (iter)) {
783 struct change_notify_entry *entry =
784 (struct change_notify_entry *) iter->data;
786 if ((entry != NULL) && (entry->change_func != NULL)) {
787 entry->change_func (entry->user_data, object);
792 /*! \brief Query visibility of the object.
793 * \par Function Description
794 * Attribute getter for the visible field within the object.
796 * \param toplevel The TOPLEVEL structure
797 * \param object The OBJECT structure to be queried
798 * \return TRUE when VISIBLE, FALSE otherwise
800 gboolean
801 o_is_visible (TOPLEVEL *toplevel, OBJECT *object)
803 g_return_val_if_fail (object != NULL, FALSE);
804 return object->visibility == VISIBLE;
807 /*! \brief Set visibility of the object.
808 * \par Function Description
809 * Set value of visibility field within the object.
810 * If resulting visibility value is changed,
811 * invalidate the bounds of the object and parent objects.
813 * \param toplevel The #TOPLEVEL structure
814 * \param object The #OBJECT structure to be modified
816 void
817 o_set_visibility (TOPLEVEL *toplevel, OBJECT *object, int visibility)
819 g_return_if_fail (object != NULL);
820 if (object->visibility != visibility) {
821 object->visibility = visibility;
822 o_bounds_invalidate (toplevel, object);