1 /* gEDA - GPL Electronic Design Automation
2 * gattrib -- gEDA component and net attribute manipulation using spreadsheet.
3 * Copyright (C) 2003-2010 Stuart D. Brorson.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 /*------------------------------------------------------------------*/
22 * \brief Functions for manipulating OBJECTs.
24 * This file holds functions involved in manipulating the OBJECT data
25 * structure. OBJECT is defined in libgeda. An OBJECT is a graphical
26 * primitive normally used in gschem. Example OBJECTs: some text,
27 * a component (complex), a pin, a line, etc.
29 * The functions herein are functions which I wrote as wrappers to the
41 /*------------------------------------------------------------------
42 * Gattrib specific includes
43 *------------------------------------------------------------------*/
44 #include <libgeda/libgeda.h> /* geda library fcns */
45 #include "../include/struct.h" /* typdef and struct declarations */
46 #include "../include/prototype.h" /* function prototypes */
47 #include "../include/globals.h"
49 #ifdef HAVE_LIBDMALLOC
54 /*------------------------------------------------------------------
55 * Gattrib specific defines
56 *------------------------------------------------------------------*/
57 #define DEFAULT_TEXT_SIZE 10
60 /* =================== Public Functions ====================== */
62 /*------------------------------------------------------------------*/
63 /*! \brief Add an attribute to an OBJECT
65 * This fcn adds a new attrib to o_current, when o_current is a
66 * component. It does it in the following
68 * -# It creates an object -- "attrib_graphic" -- and fills it in.
69 * -# It gets the position info from o_current's refdes attrib and
70 * calls o_text_new() to add position info and name=value string
72 * -# It calls o_attrib_add() to wrap attrib_graphic with (attribute OBJECT )
73 * \param toplevel TOPLEVEL structure
74 * \param o_current pointer to object to add attribute to
75 * \param new_attrib_name name of the attribute to add
76 * \param new_attrib_value value of the attribute to add
77 * \param visibility Is the attribute visible?
78 * \param show_name_value Control visibility of name and value.
81 s_object_add_comp_attrib_to_object (TOPLEVEL
*toplevel
,
83 char *new_attrib_name
,
84 char *new_attrib_value
,
88 char *name_value_pair
;
91 /* One last sanity check, then add attrib */
92 if (strlen(new_attrib_value
) != 0) {
93 name_value_pair
= g_strconcat(new_attrib_name
, "=", new_attrib_value
, NULL
);
94 s_object_attrib_add_attrib_in_object (toplevel
,
106 /*------------------------------------------------------------------*/
108 * \todo This needs to be filled in.
111 s_object_add_net_attrib_to_object (TOPLEVEL
*toplevel
,
113 char *new_attrib_name
,
114 char *new_attrib_value
)
120 /*------------------------------------------------------------------*/
121 /*! \brief Add a new attribute to an pin OBJECT
123 * Add a new attribute to o_current, when o_current is a
124 * pin. It does it in the following
126 * -# It creates an object -- "attrib_graphic" -- and fills it in.
127 * -# It gets the position info from o_current's refdes attrib and
128 * calls o_text_new() to add position info and name=value string
130 * -# It calls o_attrib_add() to wrap attrib_graphic with (attribute OBJECT )
131 * \param toplevel TOPLEVEL structure
132 * \param o_current Pointer to pin object
133 * \param new_attrib_name Name of attribute to add
134 * \parma new_attrib_value Value of attribute to add
135 * \todo Do I really need separate fcns for comps, nets, and
139 s_object_add_pin_attrib_to_object (TOPLEVEL
*toplevel
,
141 char *new_attrib_name
,
142 char *new_attrib_value
)
144 char *name_value_pair
;
146 /* One last sanity check */
147 if (strlen(new_attrib_value
) != 0) {
148 name_value_pair
= g_strconcat(new_attrib_name
, "=", new_attrib_value
, NULL
);
149 s_object_attrib_add_attrib_in_object (toplevel
,
160 /*------------------------------------------------------------------*/
161 /*! \brief Replace attribute value in object
163 * Find the instance of attrib_name on o_current, and
164 * replace its value with the new_attrib_value.
165 * \param toplevel TOPLEVEL object
166 * \param o_current object to operate on
167 * \param new_attrib_name name of attribute to replace
168 * \param new_attrib_value value to set attribute to
169 * \param visibility set visibility of attribute
170 * \param show_name_value set visibility of attribute name and value
172 void s_object_replace_attrib_in_object(TOPLEVEL
*toplevel
,
174 char *new_attrib_name
,
175 char *new_attrib_value
,
177 gint show_name_value
)
181 char *old_attrib_text
;
182 char *old_attrib_name
;
183 char *new_attrib_text
;
186 a_iter
= o_current
->attribs
;
187 while (a_iter
!= NULL
) {
188 a_current
= a_iter
->data
;
189 if (a_current
->type
== OBJ_TEXT
190 && a_current
->text
!= NULL
) { /* found an attribute */
192 /* may need to check more thoroughly here. . . . */
193 old_attrib_text
= g_strdup(a_current
->text
->string
);
194 old_attrib_name
= u_basic_breakup_string(old_attrib_text
, '=', 0);
196 if (strcmp(old_attrib_name
, new_attrib_name
) == 0) {
197 /* create attrib=value text string & stuff it back into toplevel */
198 new_attrib_text
= g_strconcat(new_attrib_name
, "=", new_attrib_value
, NULL
);
199 g_free(a_current
->text
->string
); /* remove old attrib string */
200 a_current
->text
->string
= g_strdup(new_attrib_text
); /* insert new attrib string */
201 if (visibility
!= LEAVE_VISIBILITY_ALONE
)
202 o_set_visibility (toplevel
, a_current
, visibility
);
203 if (show_name_value
!= LEAVE_NAME_VALUE_ALONE
)
204 a_current
->show_name_value
= show_name_value
;
205 g_free(new_attrib_text
);
206 g_free(old_attrib_text
);
207 g_free(old_attrib_name
);
208 return; /* we are done -- leave. */
210 g_free(old_attrib_text
);
211 g_free(old_attrib_name
);
212 } /* if (strcmp . . . . */
213 } /* if (a_current . . . . */
215 a_iter
= g_list_next (a_iter
);
218 /* if we get here, it's because we have failed to find the attrib on the component.
219 * This is an error condition. */
221 "In s_object_replace_attrib_in_object, we have failed to find the attrib %s on the component. Exiting . . .\n",
227 /*------------------------------------------------------------------*/
229 * \brief Remove attribute from object
231 * Remove an attribute from an object.
232 * \param toplevel TOPLEVEL structure
233 * \param o_current Object to remove attribute from
234 * \param new_attrib_name Name of attribute to remove
237 s_object_remove_attrib_in_object (TOPLEVEL
*toplevel
,
239 char *new_attrib_name
)
243 OBJECT
*attribute_object
;
244 char *old_attrib_text
;
245 char *old_attrib_name
;
247 a_iter
= o_current
->attribs
;
248 while (a_iter
!= NULL
) {
249 a_current
= a_iter
->data
;
250 if (a_current
->type
== OBJ_TEXT
251 && a_current
->text
!= NULL
) { /* found an attribute */
253 /* may need to check more thoroughly here. . . . */
254 old_attrib_text
= g_strdup(a_current
->text
->string
);
255 old_attrib_name
= u_basic_breakup_string(old_attrib_text
, '=', 0);
257 if (strcmp(old_attrib_name
, new_attrib_name
) == 0) {
258 /* We've found the attrib. Delete it and then return. */
261 printf("In s_object_remove_attrib_in_object, removing attrib with name = %s\n", old_attrib_name
);
264 attribute_object
= a_current
;
265 s_object_delete_text_object_in_object (toplevel
, attribute_object
);
267 g_free(old_attrib_text
);
268 g_free(old_attrib_name
);
269 return; /* we are done -- leave. */
271 g_free(old_attrib_text
);
272 g_free(old_attrib_name
);
274 a_iter
= g_list_next (a_iter
);
277 /* if we get here, it's because we have failed to find the attrib on the component.
278 * This is an error condition. */
280 "In s_object_remove_attrib_in_object, we have failed to find the attrib %s on the component. Exiting . . .\n",
287 /*------------------------------------------------------------------*/
288 /*! \brief Attach attribute to object.
290 * Attach the name=value pair to the OBJECT "object". This function
291 * was stolen from gschem/src/o_attrib.c:o_attrib_add_attrib and
292 * hacked for gattrib.
293 * \param toplevel TOPLEVEL to operate on
296 * \param show_name_value
298 * \returns pointer to the object
299 * \todo Does it need to return OBJECT?
302 s_object_attrib_add_attrib_in_object (TOPLEVEL
*toplevel
,
308 int world_x
= -1, world_y
= -1;
310 int left
, right
, top
, bottom
;
314 color
= DETACHED_ATTRIBUTE_COLOR
;
318 /* creating a toplevel or unattached attribute */
320 /* get coordinates of where to place the text object */
321 switch (o_current
->type
) {
323 world_x
= o_current
->complex->x
;
324 world_y
= o_current
->complex->y
;
325 color
= ATTRIBUTE_COLOR
;
329 world_x
= o_current
->complex->x
;
330 world_y
= o_current
->complex->y
;
331 color
= ATTRIBUTE_COLOR
;
335 fprintf(stderr
, "In s_object_attrib_add_attrib_in_object, trying to add attrib to non-complex or non-net!\n");
338 } else { /* This must be a floating attrib, but what is that !?!?!?!?! */
339 world_get_object_glist_bounds (toplevel
,
340 s_page_objects (toplevel
->page_current
),
341 &left
, &top
, &right
, &bottom
);
343 /* this really is the lower left hand corner */
347 /* printf("%d %d\n", world_x, world_y); */
348 color
= DETACHED_ATTRIBUTE_COLOR
;
351 /* first create text item */
353 printf("=== In s_object_attrib_add_attrib_in_object, about to attach new text attrib with properties:\n");
354 printf(" color = %d\n", color
);
355 printf(" text_string = %s \n", text_string
);
356 printf(" text_size = %d \n", toplevel
->text_size
);
357 printf(" visibility = %d \n", visibility
);
358 printf(" show_name_value = %d \n", show_name_value
);
361 new_obj
= o_text_new (toplevel
, OBJ_TEXT
, color
, world_x
, world_y
,
362 LOWER_LEFT
, 0, /* zero is angle */
363 text_string
, DEFAULT_TEXT_SIZE
,
364 visibility
, show_name_value
);
365 s_page_append (toplevel
, toplevel
->page_current
, new_obj
);
367 /* now toplevel->page_current->object_tail contains new text item */
369 /* now attach the attribute to the object (if o_current is not NULL) */
370 /* remember that o_current contains the object to get the attribute */
372 o_attrib_attach (toplevel
, new_obj
, o_current
, FALSE
);
375 o_selection_add (toplevel
,
376 toplevel
->page_current
->selection_list
, new_obj
);
379 toplevel
->page_current
->CHANGED
= 1;
387 /*------------------------------------------------------------------*/
388 /*! \brief Delete text object
390 * Delete the text object pointed to by text_object. This function
391 * was shamelessly stolen from gschem/src/o_delete.c and hacked
392 * for gattrib by SDB.
393 * \param toplevel TOPLEVEL to be operated on
394 * \param test_object text object to be deleted
397 s_object_delete_text_object_in_object (TOPLEVEL
*toplevel
,
398 OBJECT
* text_object
)
400 s_page_remove (toplevel
, toplevel
->page_current
, text_object
);
401 s_delete_object (toplevel
, text_object
);
402 toplevel
->page_current
->CHANGED
= 1;
406 /*------------------------------------------------------------------*/
407 /*! \brief Ensure object has a symbol file
409 * This verifies that the object has a non-null symbol file.
411 * \returns 0 = valid symbol file, 1 = no symbol file found.
413 int s_object_has_sym_file(OBJECT
*object
)
417 filename
= object
->complex_basename
;
418 if (filename
!= NULL
) {
420 printf("In s_object_has_sym_file, object has sym file = %s.\n", filename
);
425 printf("In s_object_has_sym_file, found object with no attached symbol file.\n");