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., 59 Temple Place, Suite 330, Boston, MA 02111 USA
31 #include "libgeda_priv.h"
33 #ifdef HAVE_LIBDMALLOC
37 /*! this is modified here and in o_list.c */
40 /*! \todo Finish function documentation!!!
42 * \par Function Description
45 void error_if_called(void)
47 fprintf(stderr
, "Somebody called error_if_called!\n");
51 /*! \todo Finish function documentation!!!
53 * \par Function Description
56 void exit_if_null(void *ptr
)
59 fprintf(stderr
, "gEDA: Got NULL ptr!, please e-mail maintainer\n");
66 /*! \brief Initialize an already-allocated object.
67 * \par Function Description
68 * Initializes the members of the OBJECT structure.
70 * \param [in] new_node A pointer to an allocated OBJECT
71 * \param [in] type The object type; one of the OBJ_* constants.
72 * \param [in] name A prefix for the object's session-unique name.
73 * \return A pointer to the initialized object.
75 OBJECT
*s_basic_init_object(OBJECT
*new_node
, int type
, char const *name
)
78 new_node
->sid
= global_sid
++;
79 new_node
->type
= type
;
82 new_node
->name
= g_strdup_printf("%s.%d", name
, new_node
->sid
);
84 /* Setup the bounding box */
87 new_node
->w_right
= 0;
88 new_node
->w_bottom
= 0;
89 new_node
->w_bounds_valid
= FALSE
;
91 /* Setup line/circle structs */
92 new_node
->line
= NULL
;
93 new_node
->path
= NULL
;
94 new_node
->circle
= NULL
;
97 new_node
->picture
= NULL
;
98 new_node
->text
= NULL
;
99 new_node
->complex = NULL
;
101 new_node
->tiles
= NULL
;
103 new_node
->conn_list
= NULL
;
105 new_node
->complex_basename
= NULL
;
106 new_node
->parent
= NULL
;
108 /* Setup the color */
109 new_node
->color
= DEFAULT_COLOR
;
110 new_node
->selected
= FALSE
;
111 new_node
->dont_redraw
= FALSE
;
112 new_node
->locked_color
= -1;
114 new_node
->bus_ripper_direction
= 0;
116 new_node
->action_func
= error_if_called
;
117 new_node
->sel_func
= error_if_called
;
118 new_node
->draw_func
= error_if_called
;
120 new_node
->line_end
= END_NONE
;
121 new_node
->line_type
= TYPE_SOLID
;
122 new_node
->line_width
= 0;
123 new_node
->line_space
= 0;
124 new_node
->line_length
= 0;
125 new_node
->fill_width
= 0;
126 new_node
->fill_angle1
= 0;
127 new_node
->fill_angle2
= 0;
128 new_node
->fill_pitch1
= 0;
129 new_node
->fill_pitch2
= 0;
131 new_node
->attribs
= NULL
;
132 new_node
->attached_to
= NULL
;
133 new_node
->copied_to
= NULL
;
134 new_node
->show_name_value
= SHOW_NAME_VALUE
;
135 new_node
->visibility
= VISIBLE
;
137 new_node
->pin_type
= PIN_TYPE_NET
;
138 new_node
->whichend
= -1;
144 /*! \brief Helper to allocate and initialise an object.
146 * \par Function Description
147 * Allocates memory for an OBJECT and then calls s_basic_init_object() on it.
149 * \param [in] type The sub-type of the object to create; one of the OBJ_* constants.
150 * \param [in] prefix The name prefix for the session-unique object name.
151 * \return A pointer to the fully constructed OBJECT.
153 OBJECT
*s_basic_new_object(int type
, char const *prefix
)
155 return s_basic_init_object(g_malloc(sizeof (OBJECT
)), type
, prefix
);
159 /*! \todo Finish function documentation!!!
161 * \par Function Description
164 void print_struct_forw (GList
*list
)
166 OBJECT
*o_current
=NULL
;
170 printf("TRYING to PRINT\n");
171 while (iter
!= NULL
) {
172 o_current
= (OBJECT
*)iter
->data
;
173 printf("Name: %s\n", o_current
->name
);
174 printf("Type: %d\n", o_current
->type
);
175 printf("Sid: %d\n", o_current
->sid
);
177 if (o_current
->type
== OBJ_COMPLEX
|| o_current
->type
== OBJ_PLACEHOLDER
) {
178 print_struct_forw(o_current
->complex->prim_objs
);
181 o_attrib_print (o_current
->attribs
);
184 iter
= g_list_next (iter
);
188 /*! \todo Finish function documentation!!!
190 * \par Function Description
193 void print_struct(OBJECT
*ptr
)
195 OBJECT
*o_current
=NULL
;
199 if (o_current
!= NULL
) {
200 printf("Name: %s\n", o_current
->name
);
201 printf("Type: %d\n", o_current
->type
);
202 printf("Sid: %d\n", o_current
->sid
);
203 if (o_current
->line
!= NULL
) {
204 printf("Line points.x1: %d\n", o_current
->line
->x
[0]);
205 printf("Line points.y1: %d\n", o_current
->line
->y
[0]);
206 printf("Line points.x2: %d\n", o_current
->line
->x
[1]);
207 printf("Line points.y2: %d\n", o_current
->line
->y
[1]);
210 o_attrib_print (o_current
->attribs
);
216 /*! \todo Finish function documentation!!!
218 * \par Function Description
222 s_delete_object(TOPLEVEL
*toplevel
, OBJECT
*o_current
)
224 if (o_current
!= NULL
) {
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 if (toplevel
->page_current
->object_lastplace
== o_current
) {
233 toplevel
->page_current
->object_lastplace
= NULL
;
236 if (o_current
->line
) {
237 /* printf("sdeleting line\n");*/
238 g_free(o_current
->line
);
240 /* yes this object might be in the tile system */
241 s_tile_remove_object(o_current
);
243 o_current
->line
= NULL
;
245 if (o_current
->path
) {
246 g_free(o_current
->path
);
248 o_current
->path
= NULL
;
250 /* printf("sdeleting circle\n");*/
251 g_free(o_current
->circle
);
252 o_current
->circle
= NULL
;
254 /* printf("sdeleting arc\n");*/
255 g_free(o_current
->arc
);
256 o_current
->arc
= NULL
;
258 /* printf("sdeleting box\n");*/
259 g_free(o_current
->box
);
260 o_current
->box
= NULL
;
262 if (o_current
->picture
) {
263 /* printf("sdeleting picture\n");*/
265 g_free(o_current
->picture
->file_content
);
266 if (o_current
->picture
->pixbuf
)
267 g_object_unref (o_current
->picture
->pixbuf
);
269 g_free(o_current
->picture
->filename
);
270 g_free(o_current
->picture
);
272 o_current
->picture
= NULL
;
274 if (o_current
->text
) {
275 /*printf("sdeleting text->string\n");*/
276 g_free(o_current
->text
->string
);
277 o_current
->text
->string
= NULL
;
278 g_free(o_current
->text
->disp_string
);
279 /* printf("sdeleting text\n");*/
280 g_free(o_current
->text
);
282 o_current
->text
= NULL
;
284 /* printf("sdeleting name\n");*/
285 g_free(o_current
->name
);
286 o_current
->name
= NULL
;
289 /* printf("sdeleting complex_basename\n");*/
290 g_free(o_current
->complex_basename
);
291 o_current
->complex_basename
= NULL
;
293 if (o_current
->complex) {
295 if (o_current
->complex->prim_objs
) {
296 /* printf("sdeleting complex->primitive_objects\n");*/
297 s_delete_object_glist (toplevel
, o_current
->complex->prim_objs
);
298 o_current
->complex->prim_objs
= NULL
;
301 g_free(o_current
->complex);
302 o_current
->complex = NULL
;
305 o_attrib_detach_all (toplevel
, o_current
);
307 g_free(o_current
); /* assuming it is not null */
309 o_current
=NULL
; /* misc clean up */
313 /*! \todo Finish function documentation!!!
315 * \par Function Description
318 /* deletes everything include the GList */
320 s_delete_object_glist(TOPLEVEL
*toplevel
, GList
*list
)
322 OBJECT
*o_current
=NULL
;
325 ptr
= g_list_last(list
);
327 /* do the delete backwards */
329 o_current
= (OBJECT
*) ptr
->data
;
330 s_delete_object(toplevel
, o_current
);
331 ptr
= g_list_previous (ptr
);
337 /*! \todo Finish function documentation!!!
339 * \par Function Description
342 /* used by o_text_read */
343 char *remove_nl(char *string
)
351 while(string
[i
] != '\0' && string
[i
] != '\n' && string
[i
] != '\r') {
360 /*! \todo Finish function documentation!!!
362 * \par Function Description
365 /* used by o_text_read */
366 char *remove_last_nl(char *string
)
373 len
= strlen(string
);
374 if (string
[len
-1] == '\n' || string
[len
-1] == '\r')
375 string
[len
-1] = '\0';
380 /*! \brief Expand environment variables in string.
381 * \par Function Description
382 * This function returns the passed string with environment variables
385 * The invocations of environment variable MUST be in the form
386 * '${variable_name}', '$variable_name' is not valid here. Environment
387 * variable names consists solely of letters, digits and '_'. It is
388 * possible to escape a '$' character in the string by repeating it
391 * It outputs error messages to console and leaves the malformed and
392 * bad variable names in the returned string.
394 * \param [in] string The string with variables to expand.
395 * \return A newly-allocated string with variables expanded or NULL
396 * if input string was NULL.
399 s_expand_env_variables (const gchar
*string
)
404 if (string
== NULL
) {
408 gstring
= g_string_sized_new (strlen (string
));
414 /* look for end of string or possible variable name start */
415 while (string
[i
] != '\0' && string
[i
] != '$') i
++;
416 g_string_append_len (gstring
, string
+ start
, i
- start
);
417 if (string
[i
] == '\0') {
418 /* end of string, return built string */
419 return g_string_free (gstring
, FALSE
);
425 /* look for the end of the variable name */
427 while (string
[i
] != '\0' && string
[i
] != '}') i
++;
428 if (string
[i
] == '\0') {
429 /* problem: no closing '}' to variable */
431 "Found malformed environment variable in '%s'\n",
433 g_string_append (gstring
, "$");
434 g_string_append_len (gstring
, string
+ start
, i
- start
+ 1);
440 /* test characters of variable name */
442 j
< i
&& (g_ascii_isalnum (string
[j
]) || string
[j
] == '_');
445 /* illegal character detected in variable name */
447 "Found bad character [%c] in variable name.\n",
449 g_string_append (gstring
, "${");
450 g_string_append_len (gstring
, string
+ start
, i
- start
+ 1);
452 /* extract variable name from string and expand it */
453 gchar
*variable_name
= g_strndup (string
+ start
, i
- start
);
454 const gchar
*env
= g_getenv (variable_name
);
455 g_free (variable_name
);
456 g_string_append (gstring
, (env
== NULL
) ? "" : env
);
464 g_string_append_c (gstring
, string
[i
++]);
468 /* an isolated '$', put it in output */
469 g_string_append_c (gstring
, '$');
478 /* -------------------------------------------------- */
480 /*! \brief Get the directory with the gEDA system data.
481 * \par Function description
482 * Returns the path to be searched for gEDA data shared between all
483 * users. If the GEDADATA environment variable is set, returns its
484 * value; otherwise, uses a compiled-in path.
486 * On Windows, the compiled in path is *not* used, as it might not
487 * match the path where the user has installed gEDA.
489 * \warning The returned string is owned by libgeda and should not be
490 * modified or free'd.
492 * \return the gEDA shared data path, or NULL if none could be found.
494 const char *s_path_sys_data () {
495 static const char *p
= NULL
;
497 p
= g_getenv ("GEDADATA");
499 # if !defined (_WIN32)
502 g_setenv ("GEDADATA", p
, FALSE
);
508 /*! \brief Get the directory with the gEDA system configuration.
509 * \par Function description
510 * Returns the path to be searched for gEDA configuration shared
511 * between all users. If the GEDADATARC environment variable is set,
512 * returns its value; otherwise, uses a compiled-in path. Finally
513 * fallback to using the system data path.
515 * \warning The returned string is owned by libgeda and should not be
516 * modified or free'd.
518 * \return the gEDA shared config path, or NULL if none could be
521 const char *s_path_sys_config () {
522 static const char *p
= NULL
;
524 /* If GEDADATARC is set in the environment, use that path */
526 p
= g_getenv ("GEDADATARC");
530 /* If available, use the rc directory set during configure. */
533 /* Otherwise, just use the data directory */
534 p
= s_path_sys_data ();
537 if (p
!= NULL
) g_setenv("GEDADATARC", p
, FALSE
);
541 /*! \brief Get the directory with the gEDA user configuration.
542 * \par Function description
543 * Returns the path to be searched for the current user's gEDA
544 * configuration. Currently defaults to a directory ".gEDA" in the
545 * user's home directory.
547 * \warning The returned string is owned by libgeda and should not be
548 * modified or free'd.
550 * \todo On Windows, we should use APPDATA.
552 const char *s_path_user_config () {
553 static const char *p
= NULL
;
556 const char *home
= g_getenv ("HOME");
557 if (home
== NULL
) home
= g_get_home_dir ();
558 p
= g_build_filename(home
, ".gEDA", NULL
);