libgeda

s_basic.c

Go to the documentation of this file.
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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines