Update README with new Automake requirement.
[geda-gaf.git] / libgeda / src / o_basic.c
blob6689dee82a6e7b734a2d95b851bab2fd33bfb2f9
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);
81 /*! \brief Set an #OBJECT's line options.
82 * \par Function Description
83 * This function allows a line's end, type, width, length and space to be set.
84 * See #OBJECT_END and #OBJECT_TYPE for information on valid
85 * object end and type values.
87 * \param [in] toplevel The TOPLEVEL object.
88 * \param [in,out] o_current OBJECT to set line options on.
89 * \param [in] end An OBJECT_END.
90 * \param [in] type An OBJECT_TYPE.
91 * \param [in] width Line width.
92 * \param [in] length Line length.
93 * \param [in] space Spacing between dashes/dots. Cannot be negative.
95 * \todo Make space an unsigned int and check for a max value instead.
96 * If a max value is not required, then it would simplify the code.
98 void o_set_line_options(TOPLEVEL *toplevel, OBJECT *o_current,
99 OBJECT_END end, OBJECT_TYPE type,
100 int width, int length, int space)
102 g_return_if_fail (o_current != NULL);
104 /* do some error checking / correcting */
105 switch(type) {
106 case(TYPE_SOLID):
107 length = -1;
108 space = -1;
109 break;
110 case(TYPE_DOTTED):
111 length = -1;
112 if (space < 1) {
113 space = 100;
115 break;
116 case(TYPE_DASHED):
117 case(TYPE_CENTER):
118 case(TYPE_PHANTOM):
119 if (length < 1) {
120 length = 100;
122 if (space < 1) {
123 space = 100;
125 break;
126 default:
128 break;
131 o_emit_pre_change_notify (toplevel, o_current);
133 o_current->line_width = width;
134 o_current->line_end = end;
135 o_current->line_type = type;
137 o_current->line_length = length;
138 o_current->line_space = space;
140 /* Recalculate the object's bounding box */
141 o_current->w_bounds_valid_for = NULL;
142 o_emit_change_notify (toplevel, o_current);
146 /*! \brief get #OBJECT's line properties.
147 * \par Function Description
148 * This function get's the #OBJECT's line options.
149 * See #OBJECT_END and #OBJECT_TYPE for information on valid
150 * object end and type values.
152 * \param [in] object OBJECT to read the properties
153 * \param [out] end An OBJECT_END.
154 * \param [out] type An OBJECT_TYPE.
155 * \param [out] width Line width.
156 * \param [out] length Line length.
157 * \param [out] space Spacing between dashes/dots.
158 * \return TRUE on succes, FALSE otherwise
161 gboolean o_get_line_options(OBJECT *object,
162 OBJECT_END *end, OBJECT_TYPE *type,
163 int *width, int *length, int *space)
165 if (object->type != OBJ_LINE
166 && object->type != OBJ_ARC
167 && object->type != OBJ_BOX
168 && object->type != OBJ_CIRCLE
169 && object->type != OBJ_PATH)
170 return FALSE;
172 *end = object->line_end;
173 *type = object->line_type;
174 *width = object->line_width;
175 *length = object->line_length;
176 *space = object->line_space;
178 return TRUE;
181 /*! \brief Set #OBJECT's fill options.
182 * \par Function Description
183 * This function allows an #OBJECT's fill options to be configured.
184 * See #OBJECT_FILLING for information on valid fill types.
186 * \param [in] toplevel The TOPLEVEL object.
187 * \param [in,out] o_current OBJECT to be updated.
188 * \param [in] type OBJECT_FILLING type.
189 * \param [in] width fill width.
190 * \param [in] pitch1 cross hatch line distance
191 * \param [in] angle1 cross hatch angle
192 * \param [in] pitch2 cross hatch line distance
193 * \param [in] angle2 cross hatch angle
196 void o_set_fill_options(TOPLEVEL *toplevel, OBJECT *o_current,
197 OBJECT_FILLING type, int width,
198 int pitch1, int angle1,
199 int pitch2, int angle2)
201 if(o_current == NULL) {
202 return;
205 o_emit_pre_change_notify (toplevel, o_current);
207 o_current->fill_type = type;
208 o_current->fill_width = width;
210 o_current->fill_pitch1 = pitch1;
211 o_current->fill_angle1 = angle1;
213 o_current->fill_pitch2 = pitch2;
214 o_current->fill_angle2 = angle2;
216 o_emit_change_notify (toplevel, o_current);
219 /*! \brief get #OBJECT's fill properties.
220 * \par Function Description
221 * This function get's the #OBJECT's fill options.
222 * See #OBJECT_FILLING for information on valid fill types.
224 * \param [in] object OBJECT to read the properties
225 * \param [out] type OBJECT_FILLING type
226 * \param [out] width fill width.
227 * \param [out] pitch1 cross hatch line distance
228 * \param [out] angle1 cross hatch angle
229 * \param [out] pitch2 cross hatch line distance
230 * \param [out] angle2 cross hatch angle
231 * \return TRUE on succes, FALSE otherwise
234 gboolean o_get_fill_options(OBJECT *object,
235 OBJECT_FILLING *type, int *width,
236 int *pitch1, int *angle1,
237 int *pitch2, int *angle2)
239 if (object->type != OBJ_BOX
240 && object->type != OBJ_CIRCLE
241 && object->type != OBJ_PATH)
242 return FALSE;
244 *type = object->fill_type;
245 *width = object->fill_width;
246 *pitch1 = object->fill_pitch1;
247 *angle1 = object->fill_angle1;
248 *pitch2 = object->fill_pitch2;
249 *angle2 = object->fill_angle2;
251 return TRUE;
254 /*! \brief get the base position of an object
255 * \par Function Description
256 * This function gets the position of an object in world coordinates.
258 * \param [in] toplevel The toplevel environment.
259 * \param [out] x pointer to the x-position
260 * \param [out] y pointer to the y-position
261 * \param [in] object The object to get the position.
262 * \return TRUE if successfully determined the position, FALSE otherwise
264 gboolean o_get_position (TOPLEVEL *toplevel, gint *x, gint *y, OBJECT *object)
266 gboolean (*func) (TOPLEVEL*, int*, int*, OBJECT*) = NULL;
268 switch (object->type) {
269 case OBJ_LINE: func = o_line_get_position; break;
270 case OBJ_NET: func = o_net_get_position; break;
271 case OBJ_BUS: func = o_bus_get_position; break;
272 case OBJ_BOX: func = o_box_get_position; break;
273 case OBJ_PICTURE: func = o_picture_get_position; break;
274 case OBJ_CIRCLE: func = o_circle_get_position; break;
275 case OBJ_PLACEHOLDER:
276 case OBJ_COMPLEX: func = o_complex_get_position; break;
277 case OBJ_TEXT: func = o_text_get_position; break;
278 case OBJ_PATH: func = o_path_get_position; break;
279 case OBJ_PIN: func = o_pin_get_position; break;
280 case OBJ_ARC: func = o_arc_get_position; break;
281 default:
282 g_critical ("o_get_position: object %p has bad type '%c'\n",
283 object, object->type);
286 if (func != NULL) {
287 return (*func) (toplevel, x, y, object);
289 return FALSE;
293 /*! \brief Translates an object in world coordinates
294 * \par Function Description
295 * This function translates the object <B>object</B> by
296 * <B>dx</B> and <B>dy</B>.
298 * \param [in] toplevel The toplevel environment.
299 * \param [in] dx Amount to horizontally translate object
300 * \param [in] dy Amount to vertically translate object
301 * \param [in] object The object to translate.
303 void o_translate_world (TOPLEVEL *toplevel, gint dx, gint dy, OBJECT *object)
305 void (*func) (TOPLEVEL*, int, int, OBJECT*) = NULL;
307 switch (object->type) {
308 case OBJ_LINE: func = o_line_translate_world; break;
309 case OBJ_NET: func = o_net_translate_world; break;
310 case OBJ_BUS: func = o_bus_translate_world; break;
311 case OBJ_BOX: func = o_box_translate_world; break;
312 case OBJ_PICTURE: func = o_picture_translate_world; break;
313 case OBJ_CIRCLE: func = o_circle_translate_world; break;
314 case OBJ_PLACEHOLDER:
315 case OBJ_COMPLEX: func = o_complex_translate_world; break;
316 case OBJ_TEXT: func = o_text_translate_world; break;
317 case OBJ_PATH: func = o_path_translate_world; break;
318 case OBJ_PIN: func = o_pin_translate_world; break;
319 case OBJ_ARC: func = o_arc_translate_world; break;
320 default:
321 g_critical ("o_translate_world: object %p has bad type '%c'\n",
322 object, object->type);
325 if (func != NULL) {
326 (*func) (toplevel, dx, dy, object);
331 /*! \brief Rotates an object in world coordinates
332 * \par Function Description
333 * This function rotates the object <B>object</B> about the coordinates
334 * <B>world_centerx</B> and <B>world_centery</B>, by <B>angle</B>degrees.
336 * \param [in] toplevel The toplevel environment.
337 * \param [in] world_centerx X coordinate of rotation center (world coords)
338 * \param [in] world_centery Y coordinate of rotation center (world coords)
339 * \param [in] angle Angle of rotation (degrees)
340 * \param [in] object The object to rotate.
342 void o_rotate_world (TOPLEVEL *toplevel, int world_centerx, int world_centery, int angle, OBJECT *object)
344 void (*func) (TOPLEVEL*, int, int, int, OBJECT*) = NULL;
346 switch (object->type) {
347 case OBJ_LINE: func = o_line_rotate_world; break;
348 case OBJ_NET: func = o_net_rotate_world; break;
349 case OBJ_BUS: func = o_bus_rotate_world; break;
350 case OBJ_BOX: func = o_box_rotate_world; break;
351 case OBJ_PICTURE: func = o_picture_rotate_world; break;
352 case OBJ_CIRCLE: func = o_circle_rotate_world; break;
353 case OBJ_PLACEHOLDER:
354 case OBJ_COMPLEX: func = o_complex_rotate_world; break;
355 case OBJ_TEXT: func = o_text_rotate_world; break;
356 case OBJ_PATH: func = o_path_rotate_world; break;
357 case OBJ_PIN: func = o_pin_rotate_world; break;
358 case OBJ_ARC: func = o_arc_rotate_world; break;
359 default:
360 g_critical ("o_rotate_world: object %p has bad type '%c'\n",
361 object, object->type);
364 if (func != NULL) {
365 (*func) (toplevel, world_centerx, world_centery, angle, object);
370 /*! \brief Mirrors an object in world coordinates
371 * \par Function Description
372 * This function mirrors an object about the point
373 * (<B>world_centerx</B>,<B>world_centery</B>) in world units.
375 * \param [in] toplevel The TOPLEVEL object.
376 * \param [in] world_centerx Origin x coordinate in WORLD units.
377 * \param [in] world_centery Origin y coordinate in WORLD units.
378 * \param [in,out] object The OBJECT to mirror.
380 void o_mirror_world (TOPLEVEL *toplevel, int world_centerx, int world_centery, OBJECT *object)
382 void (*func) (TOPLEVEL*, int, int, OBJECT*) = NULL;
384 switch (object->type) {
385 case OBJ_LINE: func = o_line_mirror_world; break;
386 case OBJ_NET: func = o_net_mirror_world; break;
387 case OBJ_BUS: func = o_bus_mirror_world; break;
388 case OBJ_BOX: func = o_box_mirror_world; break;
389 case OBJ_PICTURE: func = o_picture_mirror_world; break;
390 case OBJ_CIRCLE: func = o_circle_mirror_world; break;
391 case OBJ_PLACEHOLDER:
392 case OBJ_COMPLEX: func = o_complex_mirror_world; break;
393 case OBJ_TEXT: func = o_text_mirror_world; break;
394 case OBJ_PATH: func = o_path_mirror_world; break;
395 case OBJ_PIN: func = o_pin_mirror_world; break;
396 case OBJ_ARC: func = o_arc_mirror_world; break;
397 default:
398 g_critical ("o_mirror_world: object %p has bad type '%c'\n",
399 object, object->type);
402 if (func != NULL) {
403 (*func) (toplevel, world_centerx, world_centery, object);
408 /*! \brief Calculates the distance between the given point and the closest
409 * point on the given object.
411 * \param [in] toplevel The TOPLEVEL object.
412 * \param [in] object The given object.
413 * \param [in] x The x coordinate of the given point.
414 * \param [in] y The y coordinate of the given point.
415 * \return The shortest distance from the object to the point. If the
416 * distance cannot be calculated, this function returns a really large
417 * number (G_MAXDOUBLE). If an error occurs, this function returns
418 * G_MAXDOUBLE.
420 double o_shortest_distance (TOPLEVEL *toplevel, OBJECT *object, int x, int y)
422 return o_shortest_distance_full (toplevel, object, x, y, FALSE);
425 /*! \brief Calculates the distance between the given point and the closest
426 * point on the given object. Allows forcing objects to solid.
428 * \param [in] toplevel The TOPLEVEL object.
429 * \param [in] object The given object.
430 * \param [in] x The x coordinate of the given point.
431 * \param [in] y The y coordinate of the given point.
432 * \param [in] force_solid If true, force treating the object as solid.
433 * \return The shortest distance from the object to the point. If the
434 * distance cannot be calculated, this function returns a really large
435 * number (G_MAXDOUBLE). If an error occurs, this function returns
436 * G_MAXDOUBLE.
438 double o_shortest_distance_full (TOPLEVEL *toplevel, OBJECT *object,
439 int x, int y, int force_solid)
441 double shortest_distance = G_MAXDOUBLE;
442 double (*func) (TOPLEVEL *, OBJECT *, int, int, int) = NULL;
444 g_return_val_if_fail (object != NULL, G_MAXDOUBLE);
446 switch(object->type) {
447 case OBJ_BUS:
448 case OBJ_NET:
449 case OBJ_PIN:
450 case OBJ_LINE: func = o_line_shortest_distance; break;
451 case OBJ_BOX: func = o_box_shortest_distance; break;
452 case OBJ_PICTURE: func = o_picture_shortest_distance; break;
453 case OBJ_CIRCLE: func = o_circle_shortest_distance; break;
454 case OBJ_PLACEHOLDER:
455 case OBJ_COMPLEX: func = o_complex_shortest_distance; break;
456 case OBJ_TEXT: func = o_text_shortest_distance; break;
457 case OBJ_PATH: func = o_path_shortest_distance; break;
458 case OBJ_ARC: func = o_arc_shortest_distance; break;
459 default:
460 g_critical ("o_shortest_distance: object %p has bad type '%c'\n",
461 object, object->type);
464 if (func != NULL) {
465 shortest_distance = (*func) (toplevel, object, x, y, force_solid);
468 return shortest_distance;
471 /*! \brief Mark an OBJECT's cached bounds as invalid
472 * \par Function Description
473 * Recursively marks the cached bounds of the given OBJECT and its
474 * parents as having been invalidated and in need of an update. They
475 * will be recalculated next time the OBJECT's bounds are requested
476 * (e.g. via world_get_single_object_bounds() ).
477 * \param [in] toplevel
478 * \param [in] obj
480 * \todo Turn this into a macro?
482 void o_bounds_invalidate(TOPLEVEL *toplevel, OBJECT *obj)
484 do {
485 obj->w_bounds_valid_for = NULL;
486 } while ((obj = obj->parent) != NULL);
490 /*! \brief Change the color of an object
492 * \par Function Description
493 * This function changes the color of an object.
495 * \param [in] toplevel The TOPLEVEL structure.
496 * \param [in] object The OBJECT to change color.
497 * \param [in] color The new color.
499 void o_set_color (TOPLEVEL *toplevel, OBJECT *object, int color)
501 g_return_if_fail (object != NULL);
503 object->color = color;
505 if (object->type == OBJ_COMPLEX ||
506 object->type == OBJ_PLACEHOLDER)
507 o_glist_set_color (toplevel, object->complex->prim_objs, color);
511 /*! \brief Get an object's parent PAGE.
513 * \par Function Description
514 * Returns the PAGE structure which owns \a object. If \a object is
515 * not currently associated with a PAGE, returns NULL. If \a object is
516 * part of a compound object, recurses upward.
518 * \param [in] toplevel The TOPLEVEL structure.
519 * \param [in] object The OBJECT for which to retrieve the parent PAGE.
520 * \return The PAGE which owns \a object or NULL.
522 * \sa s_page_append_object() s_page_append() s_page_remove()
524 PAGE *
525 o_get_page (TOPLEVEL *toplevel, OBJECT *object)
527 if (object->parent != NULL) {
528 return o_get_page (toplevel, object->parent);
530 return object->page;
533 /*! \brief Get an object's containing complex object.
535 * \par Function Description
536 * If \a object is part of a complex #OBJECT, returns that
537 * #OBJECT. Otherwise, returns NULL.
539 * \param [in] toplevel The TOPLEVEL structure.
540 * \param [in] object The OBJECT for which to get the containing OBJECT.
541 * \return The complex OBJECT which owns \a object, or NULL.
543 OBJECT *
544 o_get_parent (TOPLEVEL *toplevel, OBJECT *object)
546 g_return_val_if_fail ((object != NULL), NULL);
548 if (object->parent != NULL) {
549 return object->parent;
551 return NULL;
554 /* Structure for each entry in a TOPLEVEL's list of registered change
555 * notification handlers */
556 struct change_notify_entry {
557 ChangeNotifyFunc pre_change_func;
558 ChangeNotifyFunc change_func;
559 void *user_data;
562 /*! \brief Add change notification handlers to a TOPLEVEL.
563 * \par Function Description
564 * Adds a set of change notification handlers to a #TOPLEVEL instance.
565 * \a pre_change_func will be called just before an object is
566 * modified, and \a change_func will be called just after an object is
567 * modified, with the affected object and the given \a user_data.
569 * \param toplevel #TOPLEVEL structure to add handlers to.
570 * \param pre_change_func Function to be called just before changes.
571 * \param change_func Function to be called just after changes.
572 * \param user_data User data to be passed to callback functions.
574 void
575 o_add_change_notify (TOPLEVEL *toplevel,
576 ChangeNotifyFunc pre_change_func,
577 ChangeNotifyFunc change_func,
578 void *user_data)
580 struct change_notify_entry *entry = g_new0 (struct change_notify_entry, 1);
581 entry->pre_change_func = pre_change_func;
582 entry->change_func = change_func;
583 entry->user_data = user_data;
584 toplevel->change_notify_funcs =
585 g_list_prepend (toplevel->change_notify_funcs, entry);
588 /*! \brief Remove change notification handlers from a TOPLEVEL.
589 * \par Function Description
590 * Removes a set of change notification handlers and their associated
591 * \a user_data from \a toplevel. If no registered set of handlers
592 * matches the given \a pre_change_func, \a change_func and \a
593 * user_data, does nothing.
595 * \see o_add_change_notify()
597 * \param toplevel #TOPLEVEL structure to remove handlers from.
598 * \param pre_change_func Function called just before changes.
599 * \param change_func Function called just after changes.
600 * \param user_data User data passed to callback functions.
602 void
603 o_remove_change_notify (TOPLEVEL *toplevel,
604 ChangeNotifyFunc pre_change_func,
605 ChangeNotifyFunc change_func,
606 void *user_data)
608 GList *iter;
609 for (iter = toplevel->change_notify_funcs;
610 iter != NULL; iter = g_list_next (iter)) {
612 struct change_notify_entry *entry =
613 (struct change_notify_entry *) iter->data;
615 if ((entry != NULL)
616 && (entry->pre_change_func == pre_change_func)
617 && (entry->change_func == change_func)
618 && (entry->user_data == user_data)) {
619 g_free (entry);
620 iter->data = NULL;
623 toplevel->change_notify_funcs =
624 g_list_remove_all (toplevel->change_notify_funcs, NULL);
627 /*! \brief Emit an object pre-change notification.
628 * \par Function Description
629 * Calls each pre-change callback function registered with #TOPLEVEL
630 * to notify listeners that \a object is about to be modified. All
631 * libgeda functions that modify #OBJECT structures should call this
632 * just before making a change to an #OBJECT.
634 * \param toplevel #TOPLEVEL structure to emit notifications from.
635 * \param object #OBJECT structure to emit notifications for.
637 void
638 o_emit_pre_change_notify (TOPLEVEL *toplevel, OBJECT *object)
640 GList *iter;
641 for (iter = toplevel->change_notify_funcs;
642 iter != NULL; iter = g_list_next (iter)) {
644 struct change_notify_entry *entry =
645 (struct change_notify_entry *) iter->data;
647 if ((entry != NULL) && (entry->pre_change_func != NULL)) {
648 entry->pre_change_func (entry->user_data, object);
653 /*! \brief Emit an object change notification.
654 * \par Function Description
655 * Calls each change callback function registered with #TOPLEVEL to
656 * notify listeners that \a object has just been modified. All
657 * libgeda functions that modify #OBJECT structures should call this
658 * just after making a change to an #OBJECT.
660 * \param toplevel #TOPLEVEL structure to emit notifications from.
661 * \param object #OBJECT structure to emit notifications for.
663 void
664 o_emit_change_notify (TOPLEVEL *toplevel, OBJECT *object)
666 GList *iter;
667 for (iter = toplevel->change_notify_funcs;
668 iter != NULL; iter = g_list_next (iter)) {
670 struct change_notify_entry *entry =
671 (struct change_notify_entry *) iter->data;
673 if ((entry != NULL) && (entry->change_func != NULL)) {
674 entry->change_func (entry->user_data, object);
679 /*! \brief Query visibility of the object.
680 * \par Function Description
681 * Attribute getter for the visible field within the object.
683 * \param toplevel The TOPLEVEL structure
684 * \param object The OBJECT structure to be queried
685 * \return TRUE when VISIBLE, FALSE otherwise
687 gboolean
688 o_is_visible (TOPLEVEL *toplevel, OBJECT *object)
690 g_return_val_if_fail (object != NULL, FALSE);
691 return object->visibility == VISIBLE;
694 /*! \brief Set visibility of the object.
695 * \par Function Description
696 * Set value of visibility field within the object.
697 * If resulting visibility value is changed,
698 * invalidate the bounds of the object and parent objects.
700 * \param toplevel The #TOPLEVEL structure
701 * \param object The #OBJECT structure to be modified
703 void
704 o_set_visibility (TOPLEVEL *toplevel, OBJECT *object, int visibility)
706 g_return_if_fail (object != NULL);
707 if (object->visibility != visibility) {
708 object->visibility = visibility;
709 o_bounds_invalidate (toplevel, object);