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
31 #include "libgeda_priv.h"
33 #ifdef HAVE_LIBDMALLOC
41 # ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
42 # define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 2
43 # define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 4
47 /*! this is modified here and in o_list.c */
50 /*! \brief Initialize an already-allocated object.
51 * \par Function Description
52 * Initializes the members of the OBJECT structure.
54 * \param [in] new_node A pointer to an allocated OBJECT
55 * \param [in] type The object type; one of the OBJ_* constants.
56 * \param [in] name A prefix for the object's session-unique name.
57 * \return A pointer to the initialized object.
59 OBJECT
*s_basic_init_object(OBJECT
*new_node
, int type
, char const *name
)
62 new_node
->sid
= global_sid
++;
63 new_node
->type
= type
;
66 new_node
->name
= g_strdup_printf("%s.%d", name
, new_node
->sid
);
68 /* Don't associate with a page, initially */
69 new_node
->page
= NULL
;
71 /* Setup the bounding box */
74 new_node
->w_right
= 0;
75 new_node
->w_bottom
= 0;
76 new_node
->w_bounds_valid
= FALSE
;
78 /* Setup line/circle structs */
79 new_node
->line
= NULL
;
80 new_node
->path
= NULL
;
81 new_node
->circle
= NULL
;
84 new_node
->picture
= NULL
;
85 new_node
->text
= NULL
;
86 new_node
->complex = NULL
;
88 new_node
->tiles
= NULL
;
90 new_node
->conn_list
= NULL
;
92 new_node
->complex_basename
= NULL
;
93 new_node
->parent
= NULL
;
96 new_node
->color
= DEFAULT_COLOR
;
97 new_node
->dont_redraw
= FALSE
;
98 new_node
->selectable
= TRUE
;
99 new_node
->selected
= FALSE
;
100 new_node
->locked_color
= -1;
102 new_node
->bus_ripper_direction
= 0;
104 new_node
->line_end
= END_NONE
;
105 new_node
->line_type
= TYPE_SOLID
;
106 new_node
->line_width
= 0;
107 new_node
->line_space
= 0;
108 new_node
->line_length
= 0;
109 new_node
->fill_width
= 0;
110 new_node
->fill_angle1
= 0;
111 new_node
->fill_angle2
= 0;
112 new_node
->fill_pitch1
= 0;
113 new_node
->fill_pitch2
= 0;
115 new_node
->attribs
= NULL
;
116 new_node
->attached_to
= NULL
;
117 new_node
->copied_to
= NULL
;
118 new_node
->show_name_value
= SHOW_NAME_VALUE
;
119 new_node
->visibility
= VISIBLE
;
121 new_node
->pin_type
= PIN_TYPE_NET
;
122 new_node
->whichend
= -1;
124 new_node
->net_num_connected
= 0;
125 new_node
->valid_num_connected
= FALSE
;
127 new_node
->weak_refs
= NULL
;
129 new_node
->attrib_notify_freeze_count
= 0;
130 new_node
->attrib_notify_pending
= 0;
132 new_node
->conn_notify_freeze_count
= 0;
133 new_node
->conn_notify_pending
= 0;
139 /*! \brief Helper to allocate and initialise an object.
141 * \par Function Description
142 * Allocates memory for an OBJECT and then calls s_basic_init_object() on it.
144 * \param [in] type The sub-type of the object to create; one of the OBJ_* constants.
145 * \param [in] prefix The name prefix for the session-unique object name.
146 * \return A pointer to the fully constructed OBJECT.
148 OBJECT
*s_basic_new_object(int type
, char const *prefix
)
150 return s_basic_init_object(g_malloc(sizeof (OBJECT
)), type
, prefix
);
154 /*! \todo Finish function documentation!!!
156 * \par Function Description
159 void print_struct_forw (GList
*list
)
161 OBJECT
*o_current
=NULL
;
165 printf("TRYING to PRINT\n");
166 while (iter
!= NULL
) {
167 o_current
= (OBJECT
*)iter
->data
;
168 printf("Name: %s\n", o_current
->name
);
169 printf("Type: %d\n", o_current
->type
);
170 printf("Sid: %d\n", o_current
->sid
);
172 if (o_current
->type
== OBJ_COMPLEX
|| o_current
->type
== OBJ_PLACEHOLDER
) {
173 print_struct_forw(o_current
->complex->prim_objs
);
176 o_attrib_print (o_current
->attribs
);
179 iter
= g_list_next (iter
);
183 /*! \todo Finish function documentation!!!
185 * \par Function Description
188 void print_struct(OBJECT
*ptr
)
190 OBJECT
*o_current
=NULL
;
194 if (o_current
!= NULL
) {
195 printf("Name: %s\n", o_current
->name
);
196 printf("Type: %d\n", o_current
->type
);
197 printf("Sid: %d\n", o_current
->sid
);
198 if (o_current
->line
!= NULL
) {
199 printf("Line points.x1: %d\n", o_current
->line
->x
[0]);
200 printf("Line points.y1: %d\n", o_current
->line
->y
[0]);
201 printf("Line points.x2: %d\n", o_current
->line
->x
[1]);
202 printf("Line points.y2: %d\n", o_current
->line
->y
[1]);
205 o_attrib_print (o_current
->attribs
);
211 /*! \todo Finish function documentation!!!
213 * \par Function Description
217 s_delete_object(TOPLEVEL
*toplevel
, OBJECT
*o_current
)
219 if (o_current
!= NULL
) {
220 /* If currently attached to a page, remove it from the page */
221 if (o_current
->page
!= NULL
) {
222 s_page_remove (toplevel
, o_current
->page
, o_current
);
225 s_conn_remove_object (toplevel
, o_current
);
227 if (o_current
->attached_to
!= NULL
) {
228 /* do the actual remove */
229 o_attrib_remove(toplevel
, &o_current
->attached_to
->attribs
, o_current
);
232 /* Don't bother with hooks for this dying object,
233 * leak the freeze count, so the object dies frozen.
235 o_attrib_freeze_hooks (toplevel
, o_current
);
236 o_attrib_detach_all (toplevel
, o_current
);
238 if (o_current
->line
) {
239 /* printf("sdeleting line\n");*/
240 g_free(o_current
->line
);
242 o_current
->line
= NULL
;
244 if (o_current
->path
) {
245 g_free(o_current
->path
);
247 o_current
->path
= NULL
;
249 /* printf("sdeleting circle\n");*/
250 g_free(o_current
->circle
);
251 o_current
->circle
= NULL
;
253 /* printf("sdeleting arc\n");*/
254 g_free(o_current
->arc
);
255 o_current
->arc
= NULL
;
257 /* printf("sdeleting box\n");*/
258 g_free(o_current
->box
);
259 o_current
->box
= NULL
;
261 if (o_current
->picture
) {
262 /* printf("sdeleting picture\n");*/
264 g_free(o_current
->picture
->file_content
);
265 if (o_current
->picture
->pixbuf
)
266 g_object_unref (o_current
->picture
->pixbuf
);
268 g_free(o_current
->picture
->filename
);
269 g_free(o_current
->picture
);
271 o_current
->picture
= NULL
;
273 if (o_current
->text
) {
274 /*printf("sdeleting text->string\n");*/
275 g_free(o_current
->text
->string
);
276 o_current
->text
->string
= NULL
;
277 g_free(o_current
->text
->disp_string
);
278 /* printf("sdeleting text\n");*/
279 g_free(o_current
->text
);
281 o_current
->text
= NULL
;
283 /* printf("sdeleting name\n");*/
284 g_free(o_current
->name
);
285 o_current
->name
= NULL
;
288 /* printf("sdeleting complex_basename\n");*/
289 g_free(o_current
->complex_basename
);
290 o_current
->complex_basename
= NULL
;
292 if (o_current
->complex) {
294 if (o_current
->complex->prim_objs
) {
295 /* printf("sdeleting complex->primitive_objects\n");*/
296 s_delete_object_glist (toplevel
, o_current
->complex->prim_objs
);
297 o_current
->complex->prim_objs
= NULL
;
300 g_free(o_current
->complex);
301 o_current
->complex = NULL
;
304 s_weakref_notify (o_current
, o_current
->weak_refs
);
306 g_free(o_current
); /* assuming it is not null */
308 o_current
=NULL
; /* misc clean up */
312 /*! \todo Finish function documentation!!!
314 * \par Function Description
317 /* deletes everything include the GList */
319 s_delete_object_glist(TOPLEVEL
*toplevel
, GList
*list
)
321 OBJECT
*o_current
=NULL
;
324 ptr
= g_list_last(list
);
326 /* do the delete backwards */
328 o_current
= (OBJECT
*) ptr
->data
;
329 s_delete_object(toplevel
, o_current
);
330 ptr
= g_list_previous (ptr
);
335 /*! \brief Add a weak reference watcher to an OBJECT.
336 * \par Function Description
337 * Adds the weak reference callback \a notify_func to \a object. When
338 * \a object is destroyed, \a notify_func will be called with two
339 * arguments: the \a object, and the \a user_data.
341 * \sa s_object_weak_unref
343 * \param [in,out] object Object to weak-reference.
344 * \param [in] notify_func Weak reference notify function.
345 * \param [in] user_data Data to be passed to \a notify_func.
348 s_object_weak_ref (OBJECT
*object
,
349 void (*notify_func
)(void *, void *),
352 g_return_if_fail (object
!= NULL
);
353 object
->weak_refs
= s_weakref_add (object
->weak_refs
, notify_func
, user_data
);
356 /*! \brief Remove a weak reference watcher from an OBJECT.
357 * \par Function Description
358 * Removes the weak reference callback \a notify_func from \a object.
360 * \sa s_object_weak_ref()
362 * \param [in,out] object Object to weak-reference.
363 * \param [in] notify_func Notify function to search for.
364 * \param [in] user_data Data to to search for.
367 s_object_weak_unref (OBJECT
*object
,
368 void (*notify_func
)(void *, void *),
371 g_return_if_fail (object
!= NULL
);
372 object
->weak_refs
= s_weakref_remove (object
->weak_refs
,
373 notify_func
, user_data
);
376 /*! \brief Add a weak pointer to an OBJECT.
377 * \par Function Description
378 * Adds the weak pointer at \a weak_pointer_loc to \a object. The
379 * value of \a weak_pointer_loc will be set to NULL when \a object is
382 * \sa s_object_remove_weak_ptr
384 * \param [in,out] object Object to weak-reference.
385 * \param [in] weak_pointer_loc Memory address of a pointer.
388 s_object_add_weak_ptr (OBJECT
*object
,
389 void *weak_pointer_loc
)
391 g_return_if_fail (object
!= NULL
);
392 object
->weak_refs
= s_weakref_add_ptr (object
->weak_refs
, weak_pointer_loc
);
395 /*! \brief Remove a weak pointer from an OBJECT.
396 * \par Function Description
397 * Removes the weak pointer at \a weak_pointer_loc from \a object.
399 * \sa s_object_add_weak_ptr()
401 * \param [in,out] object Object to weak-reference.
402 * \param [in] weak_pointer_loc Memory address of a pointer.
405 s_object_remove_weak_ptr (OBJECT
*object
,
406 void *weak_pointer_loc
)
408 g_return_if_fail (object
!= NULL
);
409 object
->weak_refs
= s_weakref_remove_ptr (object
->weak_refs
,
413 /*! \todo Finish function documentation!!!
415 * \par Function Description
418 /* used by o_text_read */
419 char *remove_nl(char *string
)
427 while(string
[i
] != '\0' && string
[i
] != '\n' && string
[i
] != '\r') {
436 /*! \todo Finish function documentation!!!
438 * \par Function Description
441 /* used by o_text_read */
442 char *remove_last_nl(char *string
)
449 len
= strlen(string
);
450 if (string
[len
-1] == '\n' || string
[len
-1] == '\r')
451 string
[len
-1] = '\0';
456 /*! \brief Expand environment variables in string.
457 * \par Function Description
458 * This function returns the passed string with environment variables
461 * The invocations of environment variable MUST be in the form
462 * '${variable_name}', '$variable_name' is not valid here. Environment
463 * variable names consists solely of letters, digits and '_'. It is
464 * possible to escape a '$' character in the string by repeating it
467 * It outputs error messages to console and leaves the malformed and
468 * bad variable names in the returned string.
470 * \param [in] string The string with variables to expand.
471 * \return A newly-allocated string with variables expanded or NULL
472 * if input string was NULL.
475 s_expand_env_variables (const gchar
*string
)
480 if (string
== NULL
) {
484 gstring
= g_string_sized_new (strlen (string
));
490 /* look for end of string or possible variable name start */
491 while (string
[i
] != '\0' && string
[i
] != '$') i
++;
492 g_string_append_len (gstring
, string
+ start
, i
- start
);
493 if (string
[i
] == '\0') {
494 /* end of string, return built string */
495 return g_string_free (gstring
, FALSE
);
501 /* look for the end of the variable name */
503 while (string
[i
] != '\0' && string
[i
] != '}') i
++;
504 if (string
[i
] == '\0') {
505 /* problem: no closing '}' to variable */
507 "Found malformed environment variable in '%s'\n",
509 g_string_append (gstring
, "$");
510 g_string_append_len (gstring
, string
+ start
, i
- start
+ 1);
516 /* test characters of variable name */
518 j
< i
&& (g_ascii_isalnum (string
[j
]) || string
[j
] == '_');
521 /* illegal character detected in variable name */
523 "Found bad character [%c] in variable name.\n",
525 g_string_append (gstring
, "${");
526 g_string_append_len (gstring
, string
+ start
, i
- start
+ 1);
528 /* extract variable name from string and expand it */
529 gchar
*variable_name
= g_strndup (string
+ start
, i
- start
);
530 const gchar
*env
= g_getenv (variable_name
);
531 g_free (variable_name
);
532 g_string_append (gstring
, (env
== NULL
) ? "" : env
);
540 g_string_append_c (gstring
, string
[i
++]);
544 /* an isolated '$', put it in output */
545 g_string_append_c (gstring
, '$');
554 /* -------------------------------------------------- */
558 /* Get a module handle for the libgeda DLL.
560 * Adapted from GLib, originally licensed under LGPLv2+. */
562 libgeda_module_handle ()
564 typedef BOOL (WINAPI
*t_GetModuleHandleExA
) (DWORD
, LPCTSTR
, HMODULE
*);
565 static t_GetModuleHandleExA p_GetModuleHandleExA
= NULL
;
566 static gconstpointer address
= (void (*)(void)) &libgeda_module_handle
;
567 static HMODULE hmodule
= NULL
;
569 if (hmodule
!= NULL
) return (gpointer
) hmodule
;
571 if (p_GetModuleHandleExA
== NULL
) {
572 p_GetModuleHandleExA
=
573 (t_GetModuleHandleExA
) GetProcAddress (GetModuleHandle ("kernel32.dll"),
574 "GetModuleHandleExA");
577 if (p_GetModuleHandleExA
== NULL
||
578 !(*p_GetModuleHandleExA
) (GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
|
579 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
580 address
, &hmodule
)) {
581 MEMORY_BASIC_INFORMATION mbi
;
582 VirtualQuery (address
, &mbi
, sizeof (mbi
));
583 hmodule
= (HMODULE
) mbi
.AllocationBase
;
586 return (gpointer
) hmodule
;
589 #endif /* G_OS_WIN32 */
591 /*! \brief Get the directory with the gEDA system data.
592 * \par Function description
593 * Returns the path to be searched for gEDA data shared between all
594 * users. If the GEDADATA environment variable is set, returns its
595 * value; otherwise, uses a compiled-in path.
597 * On Windows, the compiled in path is *not* used, as it might not
598 * match the path where the user has installed gEDA.
600 * \warning The returned string is owned by libgeda and should not be
601 * modified or free'd.
603 * \todo On UNIX platforms we should follow the XDG Base Directory
606 * \return the gEDA shared data path, or NULL if none could be found.
608 const char *s_path_sys_data () {
609 static const char *p
= NULL
;
610 /* If GEDADATA is set in the environment, use that path */
612 p
= g_getenv ("GEDADATA");
615 # if defined (G_OS_WIN32)
616 /* On Windows, guess the path from the location of the libgeda
619 g_win32_get_package_installation_directory_of_module (libgeda_module_handle ());
620 p
= g_build_filename (d
, "share", "gEDA", NULL
);
623 /* On other platforms, use the compiled-in path */
626 g_setenv ("GEDADATA", p
, FALSE
);
631 /*! \brief Get the directory with the gEDA system configuration.
632 * \par Function description
633 * Returns the path to be searched for gEDA configuration shared
634 * between all users. If the GEDADATARC environment variable is set,
635 * returns its value; otherwise, uses a compiled-in path. Finally
636 * fallback to using the system data path.
638 * \warning The returned string is owned by libgeda and should not be
639 * modified or free'd.
641 * \todo On UNIX platforms we should follow the XDG Base Directory
644 * \return the gEDA shared config path, or NULL if none could be
647 const char *s_path_sys_config () {
648 static const char *p
= NULL
;
650 /* If GEDADATARC is set in the environment, use that path */
652 p
= g_getenv ("GEDADATARC");
655 #if defined (GEDARCDIR) && !defined(_WIN32)
656 /* If available, use the rc directory set during configure. */
659 /* Otherwise, just use the data directory */
660 p
= s_path_sys_data ();
663 if (p
!= NULL
) g_setenv("GEDADATARC", p
, FALSE
);
667 /*! \brief Get the directory with the gEDA user configuration.
668 * \par Function description
669 * Returns the path to be searched for the current user's gEDA
670 * configuration. Currently defaults to a directory ".gEDA" in the
671 * user's home directory.
673 * \warning The returned string is owned by libgeda and should not be
674 * modified or free'd.
676 * \todo On Windows, we should use APPDATA.
678 * \todo On UNIX platforms we should follow the XDG Base Directory
681 const char *s_path_user_config () {
682 static const char *p
= NULL
;
685 const char *home
= g_getenv ("HOME");
686 if (home
== NULL
) home
= g_get_home_dir ();
687 p
= g_build_filename(home
, ".gEDA", NULL
);