libgeda
|
00001 /* gEDA - GPL Electronic Design Automation 00002 * libgeda - gEDA's library 00003 * Copyright (C) 1998-2010 Ales Hvezda 00004 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details) 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 #include <config.h> 00021 00022 #include <stdio.h> 00023 #include <ctype.h> 00024 #ifdef HAVE_STDLIB_H 00025 #include <stdlib.h> 00026 #endif 00027 #ifdef HAVE_STRING_H 00028 #include <string.h> 00029 #endif 00030 00031 #include "libgeda_priv.h" 00032 00033 #ifdef HAVE_LIBDMALLOC 00034 #include <dmalloc.h> 00035 #endif 00036 00037 #ifdef G_OS_WIN32 00038 # define STRICT 00039 # include <windows.h> 00040 # undef STRICT 00041 # ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 00042 # define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 2 00043 # define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 4 00044 # endif 00045 #endif 00046 00048 int global_sid=0; 00049 00059 OBJECT *s_basic_init_object(OBJECT *new_node, int type, char const *name) 00060 { 00061 /* setup sid */ 00062 new_node->sid = global_sid++; 00063 new_node->type = type; 00064 00065 /* Setup the name */ 00066 new_node->name = g_strdup_printf("%s.%d", name, new_node->sid); 00067 00068 /* Don't associate with a page, initially */ 00069 new_node->page = NULL; 00070 00071 /* Setup the bounding box */ 00072 new_node->w_top = 0; 00073 new_node->w_left = 0; 00074 new_node->w_right = 0; 00075 new_node->w_bottom = 0; 00076 new_node->w_bounds_valid = FALSE; 00077 00078 /* Setup line/circle structs */ 00079 new_node->line = NULL; 00080 new_node->path = NULL; 00081 new_node->circle = NULL; 00082 new_node->arc = NULL; 00083 new_node->box = NULL; 00084 new_node->picture = NULL; 00085 new_node->text = NULL; 00086 new_node->complex = NULL; 00087 00088 new_node->tiles = NULL; 00089 00090 new_node->conn_list = NULL; 00091 00092 new_node->complex_basename = NULL; 00093 new_node->parent = NULL; 00094 00095 /* Setup the color */ 00096 new_node->color = DEFAULT_COLOR; 00097 new_node->dont_redraw = FALSE; 00098 new_node->selectable = TRUE; 00099 new_node->selected = FALSE; 00100 new_node->locked_color = -1; 00101 00102 new_node->bus_ripper_direction = 0; 00103 00104 new_node->line_end = END_NONE; 00105 new_node->line_type = TYPE_SOLID; 00106 new_node->line_width = 0; 00107 new_node->line_space = 0; 00108 new_node->line_length = 0; 00109 new_node->fill_width = 0; 00110 new_node->fill_angle1 = 0; 00111 new_node->fill_angle2 = 0; 00112 new_node->fill_pitch1 = 0; 00113 new_node->fill_pitch2 = 0; 00114 00115 new_node->attribs = NULL; 00116 new_node->attached_to = NULL; 00117 new_node->copied_to = NULL; 00118 new_node->show_name_value = SHOW_NAME_VALUE; 00119 new_node->visibility = VISIBLE; 00120 00121 new_node->pin_type = PIN_TYPE_NET; 00122 new_node->whichend = -1; 00123 00124 new_node->net_num_connected = 0; 00125 new_node->valid_num_connected = FALSE; 00126 00127 new_node->weak_refs = NULL; 00128 00129 new_node->attrib_notify_freeze_count = 0; 00130 new_node->attrib_notify_pending = 0; 00131 00132 new_node->conn_notify_freeze_count = 0; 00133 new_node->conn_notify_pending = 0; 00134 00135 return(new_node); 00136 } 00137 00138 00148 OBJECT *s_basic_new_object(int type, char const *prefix) 00149 { 00150 return s_basic_init_object(g_malloc(sizeof (OBJECT)), type, prefix); 00151 } 00152 00153 00159 void print_struct_forw (GList *list) 00160 { 00161 OBJECT *o_current=NULL; 00162 GList *iter; 00163 00164 iter = list; 00165 printf("TRYING to PRINT\n"); 00166 while (iter != NULL) { 00167 o_current = (OBJECT *)iter->data; 00168 printf("Name: %s\n", o_current->name); 00169 printf("Type: %d\n", o_current->type); 00170 printf("Sid: %d\n", o_current->sid); 00171 00172 if (o_current->type == OBJ_COMPLEX || o_current->type == OBJ_PLACEHOLDER) { 00173 print_struct_forw(o_current->complex->prim_objs); 00174 } 00175 00176 o_attrib_print (o_current->attribs); 00177 00178 printf("----\n"); 00179 iter = g_list_next (iter); 00180 } 00181 } 00182 00188 void print_struct(OBJECT *ptr) 00189 { 00190 OBJECT *o_current=NULL; 00191 00192 o_current = ptr; 00193 00194 if (o_current != NULL) { 00195 printf("Name: %s\n", o_current->name); 00196 printf("Type: %d\n", o_current->type); 00197 printf("Sid: %d\n", o_current->sid); 00198 if (o_current->line != NULL) { 00199 printf("Line points.x1: %d\n", o_current->line->x[0]); 00200 printf("Line points.y1: %d\n", o_current->line->y[0]); 00201 printf("Line points.x2: %d\n", o_current->line->x[1]); 00202 printf("Line points.y2: %d\n", o_current->line->y[1]); 00203 } 00204 00205 o_attrib_print (o_current->attribs); 00206 00207 printf("----\n"); 00208 } 00209 } 00210 00216 void 00217 s_delete_object(TOPLEVEL *toplevel, OBJECT *o_current) 00218 { 00219 if (o_current != NULL) { 00220 /* If currently attached to a page, remove it from the page */ 00221 if (o_current->page != NULL) { 00222 s_page_remove (toplevel, o_current->page, o_current); 00223 } 00224 00225 s_conn_remove_object (toplevel, o_current); 00226 00227 if (o_current->attached_to != NULL) { 00228 /* do the actual remove */ 00229 o_attrib_remove(toplevel, &o_current->attached_to->attribs, o_current); 00230 } 00231 00232 /* Don't bother with hooks for this dying object, 00233 * leak the freeze count, so the object dies frozen. 00234 */ 00235 o_attrib_freeze_hooks (toplevel, o_current); 00236 o_attrib_detach_all (toplevel, o_current); 00237 00238 if (o_current->line) { 00239 /* printf("sdeleting line\n");*/ 00240 g_free(o_current->line); 00241 } 00242 o_current->line = NULL; 00243 00244 if (o_current->path) { 00245 g_free(o_current->path); 00246 } 00247 o_current->path = NULL; 00248 00249 /* printf("sdeleting circle\n");*/ 00250 g_free(o_current->circle); 00251 o_current->circle = NULL; 00252 00253 /* printf("sdeleting arc\n");*/ 00254 g_free(o_current->arc); 00255 o_current->arc = NULL; 00256 00257 /* printf("sdeleting box\n");*/ 00258 g_free(o_current->box); 00259 o_current->box = NULL; 00260 00261 if (o_current->picture) { 00262 /* printf("sdeleting picture\n");*/ 00263 00264 g_free(o_current->picture->file_content); 00265 if (o_current->picture->pixbuf) 00266 g_object_unref (o_current->picture->pixbuf); 00267 00268 g_free(o_current->picture->filename); 00269 g_free(o_current->picture); 00270 } 00271 o_current->picture = NULL; 00272 00273 if (o_current->text) { 00274 /*printf("sdeleting text->string\n");*/ 00275 g_free(o_current->text->string); 00276 o_current->text->string = NULL; 00277 g_free(o_current->text->disp_string); 00278 /* printf("sdeleting text\n");*/ 00279 g_free(o_current->text); 00280 } 00281 o_current->text = NULL; 00282 00283 /* printf("sdeleting name\n");*/ 00284 g_free(o_current->name); 00285 o_current->name = NULL; 00286 00287 00288 /* printf("sdeleting complex_basename\n");*/ 00289 g_free(o_current->complex_basename); 00290 o_current->complex_basename = NULL; 00291 00292 if (o_current->complex) { 00293 00294 if (o_current->complex->prim_objs) { 00295 /* printf("sdeleting complex->primitive_objects\n");*/ 00296 s_delete_object_glist (toplevel, o_current->complex->prim_objs); 00297 o_current->complex->prim_objs = NULL; 00298 } 00299 00300 g_free(o_current->complex); 00301 o_current->complex = NULL; 00302 } 00303 00304 s_weakref_notify (o_current, o_current->weak_refs); 00305 00306 g_free(o_current); /* assuming it is not null */ 00307 00308 o_current=NULL; /* misc clean up */ 00309 } 00310 } 00311 00317 /* deletes everything include the GList */ 00318 void 00319 s_delete_object_glist(TOPLEVEL *toplevel, GList *list) 00320 { 00321 OBJECT *o_current=NULL; 00322 GList *ptr; 00323 00324 ptr = g_list_last(list); 00325 00326 /* do the delete backwards */ 00327 while(ptr != NULL) { 00328 o_current = (OBJECT *) ptr->data; 00329 s_delete_object(toplevel, o_current); 00330 ptr = g_list_previous (ptr); 00331 } 00332 g_list_free(list); 00333 } 00334 00347 void 00348 s_object_weak_ref (OBJECT *object, 00349 void (*notify_func)(void *, void *), 00350 void *user_data) 00351 { 00352 g_return_if_fail (object != NULL); 00353 object->weak_refs = s_weakref_add (object->weak_refs, notify_func, user_data); 00354 } 00355 00366 void 00367 s_object_weak_unref (OBJECT *object, 00368 void (*notify_func)(void *, void *), 00369 void *user_data) 00370 { 00371 g_return_if_fail (object != NULL); 00372 object->weak_refs = s_weakref_remove (object->weak_refs, 00373 notify_func, user_data); 00374 } 00375 00387 void 00388 s_object_add_weak_ptr (OBJECT *object, 00389 void *weak_pointer_loc) 00390 { 00391 g_return_if_fail (object != NULL); 00392 object->weak_refs = s_weakref_add_ptr (object->weak_refs, weak_pointer_loc); 00393 } 00394 00404 void 00405 s_object_remove_weak_ptr (OBJECT *object, 00406 void *weak_pointer_loc) 00407 { 00408 g_return_if_fail (object != NULL); 00409 object->weak_refs = s_weakref_remove_ptr (object->weak_refs, 00410 weak_pointer_loc); 00411 } 00412 00418 /* used by o_text_read */ 00419 char *remove_nl(char *string) 00420 { 00421 int i; 00422 00423 if (!string) 00424 return NULL; 00425 00426 i = 0; 00427 while(string[i] != '\0' && string[i] != '\n' && string[i] != '\r') { 00428 i++; 00429 } 00430 00431 string[i] = '\0'; 00432 00433 return(string); 00434 } 00435 00441 /* used by o_text_read */ 00442 char *remove_last_nl(char *string) 00443 { 00444 int len; 00445 00446 if (!string) 00447 return NULL; 00448 00449 len = strlen(string); 00450 if (string[len-1] == '\n' || string[len-1] == '\r') 00451 string[len-1] = '\0'; 00452 00453 return(string); 00454 } 00455 00474 gchar* 00475 s_expand_env_variables (const gchar *string) 00476 { 00477 GString *gstring; 00478 gint i; 00479 00480 if (string == NULL) { 00481 return NULL; 00482 } 00483 00484 gstring = g_string_sized_new (strlen (string)); 00485 i = 0; 00486 while (TRUE) { 00487 gint start; 00488 00489 start = i; 00490 /* look for end of string or possible variable name start */ 00491 while (string[i] != '\0' && string[i] != '$') i++; 00492 g_string_append_len (gstring, string + start, i - start); 00493 if (string[i] == '\0') { 00494 /* end of string, return built string */ 00495 return g_string_free (gstring, FALSE); 00496 } 00497 00498 i++; 00499 switch (string[i]) { 00500 case ('{'): 00501 /* look for the end of the variable name */ 00502 start = i; 00503 while (string[i] != '\0' && string[i] != '}') i++; 00504 if (string[i] == '\0') { 00505 /* problem: no closing '}' to variable */ 00506 fprintf (stderr, 00507 "Found malformed environment variable in '%s'\n", 00508 string); 00509 g_string_append (gstring, "$"); 00510 g_string_append_len (gstring, string + start, i - start + 1); 00511 } else { 00512 gint j; 00513 00514 /* discard "${" */ 00515 start = start + 1; 00516 /* test characters of variable name */ 00517 for (j = start; 00518 j < i && (g_ascii_isalnum (string[j]) || string[j] == '_'); 00519 j++); 00520 if (i != j) { 00521 /* illegal character detected in variable name */ 00522 fprintf (stderr, 00523 "Found bad character [%c] in variable name.\n", 00524 string[j]); 00525 g_string_append (gstring, "${"); 00526 g_string_append_len (gstring, string + start, i - start + 1); 00527 } else { 00528 /* extract variable name from string and expand it */ 00529 gchar *variable_name = g_strndup (string + start, i - start); 00530 const gchar *env = g_getenv (variable_name); 00531 g_free (variable_name); 00532 g_string_append (gstring, (env == NULL) ? "" : env); 00533 } 00534 i++; 00535 } 00536 break; 00537 00538 case ('$'): 00539 /* an escaped '$' */ 00540 g_string_append_c (gstring, string[i++]); 00541 break; 00542 00543 default: 00544 /* an isolated '$', put it in output */ 00545 g_string_append_c (gstring, '$'); 00546 } 00547 } 00548 00549 /* never reached */ 00550 return NULL; 00551 } 00552 00553 00554 /* -------------------------------------------------- */ 00555 00556 #ifdef G_OS_WIN32 00557 00558 /* Get a module handle for the libgeda DLL. 00559 * 00560 * Adapted from GLib, originally licensed under LGPLv2+. */ 00561 static gpointer 00562 libgeda_module_handle () 00563 { 00564 typedef BOOL (WINAPI *t_GetModuleHandleExA) (DWORD, LPCTSTR, HMODULE *); 00565 static t_GetModuleHandleExA p_GetModuleHandleExA = NULL; 00566 static gconstpointer address = (void (*)(void)) &libgeda_module_handle; 00567 static HMODULE hmodule = NULL; 00568 00569 if (hmodule != NULL) return (gpointer) hmodule; 00570 00571 if (p_GetModuleHandleExA == NULL) { 00572 p_GetModuleHandleExA = 00573 (t_GetModuleHandleExA) GetProcAddress (GetModuleHandle ("kernel32.dll"), 00574 "GetModuleHandleExA"); 00575 } 00576 00577 if (p_GetModuleHandleExA == NULL || 00578 !(*p_GetModuleHandleExA) (GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | 00579 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, 00580 address, &hmodule)) { 00581 MEMORY_BASIC_INFORMATION mbi; 00582 VirtualQuery (address, &mbi, sizeof (mbi)); 00583 hmodule = (HMODULE) mbi.AllocationBase; 00584 } 00585 00586 return (gpointer) hmodule; 00587 } 00588 00589 #endif /* G_OS_WIN32 */ 00590 00608 const char *s_path_sys_data () { 00609 static const char *p = NULL; 00610 /* If GEDADATA is set in the environment, use that path */ 00611 if (p == NULL) { 00612 p = g_getenv ("GEDADATA"); 00613 } 00614 if (p == NULL) { 00615 # if defined (G_OS_WIN32) 00616 /* On Windows, guess the path from the location of the libgeda 00617 * DLL. */ 00618 gchar *d = 00619 g_win32_get_package_installation_directory_of_module (libgeda_module_handle ()); 00620 p = g_build_filename (d, "share", "gEDA", NULL); 00621 g_free (d); 00622 # else 00623 /* On other platforms, use the compiled-in path */ 00624 p = GEDADATADIR; 00625 # endif 00626 g_setenv ("GEDADATA", p, FALSE); 00627 } 00628 return p; 00629 } 00630 00647 const char *s_path_sys_config () { 00648 static const char *p = NULL; 00649 00650 /* If GEDADATARC is set in the environment, use that path */ 00651 if (p == NULL) { 00652 p = g_getenv ("GEDADATARC"); 00653 } 00654 if (p == NULL) { 00655 #if defined (GEDARCDIR) && !defined(_WIN32) 00656 /* If available, use the rc directory set during configure. */ 00657 p = GEDARCDIR; 00658 #else 00659 /* Otherwise, just use the data directory */ 00660 p = s_path_sys_data (); 00661 #endif 00662 } 00663 if (p != NULL) g_setenv("GEDADATARC", p, FALSE); 00664 return p; 00665 } 00666 00681 const char *s_path_user_config () { 00682 static const char *p = NULL; 00683 00684 if (p == NULL) { 00685 const char *home = g_getenv ("HOME"); 00686 if (home == NULL) home = g_get_home_dir (); 00687 p = g_build_filename(home, ".gEDA", NULL); 00688 } 00689 return p; 00690 }