1 /* gEDA - GPL Electronic Design Automation
2 * gattrib -- gEDA component and net attribute manipulation using spreadsheet.
3 * Copyright (C) 2003-2007 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA
20 /*------------------------------------------------------------------
21 * This file holds fcns involved in manipulating the OBJECT data
22 * structure. OBJECT is defined in libgeda. An OBJECT is a graphical
23 * primitive normally used in gschem. Example OBJECTs: some text,
24 * a component (complex), a pin, a line, etc.
26 * The fcns herein are fcns which I wrote as wrappers to the
28 *------------------------------------------------------------------ */
38 /*------------------------------------------------------------------
39 * Gattrib specific includes
40 *------------------------------------------------------------------*/
41 #include <libgeda/libgeda.h> /* geda library fcns */
42 #include "../include/struct.h" /* typdef and struct declarations */
43 #include "../include/prototype.h" /* function prototypes */
44 #include "../include/globals.h"
46 #ifdef HAVE_LIBDMALLOC
51 /*------------------------------------------------------------------
52 * Gattrib specific defines
53 *------------------------------------------------------------------*/
54 #define DEFAULT_TEXT_SIZE 10
57 /* =================== Public Functions ====================== */
59 /*------------------------------------------------------------------*/
60 /*! \brief This fcn adds a new attrib to o_current, when o_current is a
61 * component. It does it in the following
63 * 1. It creates an object -- "attrib_graphic" -- and fills it in.
64 * 2. It gets the position info from o_current's refdes attrib and
65 * calls o_text_new to add pos info and name=value string
67 * 3. It calls o_attrib_add to wrap attrib_graphic with (attribute OBJECT )
69 *------------------------------------------------------------------ */
70 void s_object_add_comp_attrib_to_object(OBJECT
*o_current
,
71 char *new_attrib_name
,
72 char *new_attrib_value
,
76 char *name_value_pair
;
78 /* One last sanity check, then add attrib */
79 if (strlen(new_attrib_value
) != 0) {
80 name_value_pair
= g_strconcat(new_attrib_name
, "=", new_attrib_value
, NULL
);
81 s_object_attrib_add_attrib_in_object(pr_current
, name_value_pair
, visibility
,
82 show_name_value
, o_current
);
89 /*------------------------------------------------------------------*/
90 /*! /brief This needs to be filled in.
92 *------------------------------------------------------------------*/
93 void s_object_add_net_attrib_to_object(OBJECT
*o_current
, char *new_attrib_name
,
94 char *new_attrib_value
)
100 /*------------------------------------------------------------------*/
101 /*! \brief This fcn adds a new attrib to o_current, when o_current is a
102 * pin. It does it in the following
104 * 1. It creates an object -- "attrib_graphic" -- and fills it in.
105 * 2. It gets the position info from o_current's refdes attrib and
106 * calls o_text_new to add pos info and name=value string
108 * 3. It calls o_attrib_add to wrap attrib_graphic with (attribute OBJECT )
109 * Question: Do I really need separate fcns for comps, nets, and
112 *------------------------------------------------------------------ */
113 void s_object_add_pin_attrib_to_object(OBJECT
*o_current
, char *new_attrib_name
,
114 char *new_attrib_value
)
116 char *name_value_pair
;
118 /* One last sanity check */
119 if (strlen(new_attrib_value
) != 0) {
120 name_value_pair
= g_strconcat(new_attrib_name
, "=", new_attrib_value
, NULL
);
121 s_object_attrib_add_attrib_in_object(pr_current
, name_value_pair
,
122 INVISIBLE
, SHOW_NAME_VALUE
, o_current
);
128 /*------------------------------------------------------------------*/
129 /*! \brief This fcn finds the instance of attrib_name on o_current, and
130 * replaces it's value wiht new_attrib_value.
132 *------------------------------------------------------------------*/
133 void s_object_replace_attrib_in_object(OBJECT
*o_current
,
134 char *new_attrib_name
,
135 char *new_attrib_value
,
137 gint show_name_value
)
141 char const *old_attrib_text
;
142 char *old_attrib_name
;
144 a_iter
= o_current
->attribs
;
145 while (a_iter
!= NULL
) {
146 a_current
= a_iter
->data
;
147 if (a_current
->type
== OBJ_TEXT
148 && a_current
->text
!= NULL
) { /* found an attribute */
150 /* may need to check more thoroughly here. . . . */
151 old_attrib_text
= o_text_get_string(a_current
);
152 old_attrib_name
= u_basic_breakup_string(old_attrib_text
, '=', 0);
154 if (strcmp(old_attrib_name
, new_attrib_name
) == 0) {
155 /* create attrib=value text string & stuff it back into pr_current */
156 o_text_take_string(a_current
, g_strconcat(new_attrib_name
, "=",
157 new_attrib_value
, NULL
));
158 o_text_change(a_current
, NULL
, visibility
, show_name_value
);
159 g_free(old_attrib_name
);
160 return; /* we are done -- leave. */
162 g_free(old_attrib_name
);
163 } /* if (strcmp . . . . */
164 } /* if (a_current . . . . */
166 a_iter
= g_list_next (a_iter
);
169 /* if we get here, it's because we have failed to find the attrib on the component.
170 * This is an error condition. */
172 "In s_object_replace_attrib_in_object, we have failed to find the attrib %s on the component. Exiting . . .\n",
178 /*------------------------------------------------------------------*/
179 /*! \brief This fcn removes attrib from o_current.
181 *------------------------------------------------------------------*/
182 void s_object_remove_attrib_in_object(OBJECT
*o_current
, char *new_attrib_name
)
186 OBJECT
*attribute_object
;
187 char const *old_attrib_text
;
188 char *old_attrib_name
;
190 a_iter
= o_current
->attribs
;
191 while (a_iter
!= NULL
) {
192 a_current
= a_iter
->data
;
193 if (a_current
->type
== OBJ_TEXT
194 && a_current
->text
!= NULL
) { /* found an attribute */
196 /* may need to check more thoroughly here. . . . */
197 old_attrib_text
= o_text_get_string(a_current
);
198 old_attrib_name
= u_basic_breakup_string(old_attrib_text
, '=', 0);
200 if (strcmp(old_attrib_name
, new_attrib_name
) == 0) {
201 /* We've found the attrib. Delete it and then return. */
203 printf("In s_object_remove_attrib_in_object, removing attrib with name = %s\n", old_attrib_name
);
206 attribute_object
= a_current
;
207 s_object_delete_text_object_in_object(pr_current
, attribute_object
);
209 g_free(old_attrib_name
);
210 return; /* we are done -- leave. */
212 g_free(old_attrib_name
);
214 a_iter
= g_list_next (a_iter
);
217 /* if we get here, it's because we have failed to find the attrib on the component.
218 * This is an error condition. */
220 "In s_object_remove_attrib_in_object, we have failed to find the attrib %s on the component. Exiting . . .\n",
227 /*------------------------------------------------------------------*/
228 /*! \brief This fcn attaches the name=value pair to the OBJECT "object" It
229 * was stolen from gschem/src/o_attrib.c:o_attrib_add_attrib and
230 * hacked for gattrib. Does it need to return OBJECT?
232 *------------------------------------------------------------------*/
233 OBJECT
*s_object_attrib_add_attrib_in_object(TOPLEVEL
*toplevel
,
239 int world_x
= -1, world_y
= -1;
241 int left
, right
, top
, bottom
;
245 color
= toplevel
->detachedattr_color
;
249 /* creating a toplevel or unattached attribute */
251 /* get coordinates of where to place the text object */
252 switch (o_current
->type
) {
254 world_x
= o_current
->complex->x
;
255 world_y
= o_current
->complex->y
;
256 color
= toplevel
->attribute_color
;
260 world_x
= o_current
->complex->x
;
261 world_y
= o_current
->complex->y
;
262 color
= toplevel
->attribute_color
;
266 fprintf(stderr
, "In s_object_attrib_add_attrib_in_object, trying to add attrib to non-complex or non-net!\n");
269 } else { /* This must be a floating attrib, but what is that !?!?!?!?! */
270 world_get_object_list_bounds(toplevel
->page_current
->object_head
, LIST_KIND_HEAD
,
271 &left
, &top
, &right
, &bottom
);
273 /* this really is the lower left hand corner */
277 /* printf("%d %d\n", world_x, world_y); */
278 color
= toplevel
->detachedattr_color
;
281 /* first create text item */
283 printf("=== In s_object_attrib_add_attrib_in_object, about to attach new text attrib with properties:\n");
284 printf(" color = %d\n", color
);
285 printf(" text_string = %s \n", text_string
);
286 printf(" visibility = %d \n", visibility
);
287 printf(" show_name_value = %d \n", show_name_value
);
290 new_obj
= o_text_new(toplevel
, OBJ_TEXT
, color
, world_x
, world_y
,
291 LOWER_LEFT
, 0, /* zero is angle */
292 text_string
, DEFAULT_TEXT_SIZE
,
293 visibility
, show_name_value
);
294 s_page_append(toplevel
->page_current
, new_obj
);
296 /* now toplevel->page_current->object_tail contains new text item */
298 /* now attach the attribute to the object (if o_current is not NULL) */
299 /* remember that o_current contains the object to get the attribute */
301 o_attrib_attach(toplevel
, toplevel
->page_current
->object_tail
,
305 o_selection_add(toplevel
->page_current
->selection_list
,
306 toplevel
->page_current
->object_tail
);
309 toplevel
->page_current
->CHANGED
= 1;
311 return (toplevel
->page_current
->object_tail
);
314 /*------------------------------------------------------------------*/
315 /*! \brief This fcn deletes the text object pointed to by text_object. It
316 * was shamelessly stolen from gschem/src/o_delete.c and hacked
317 * for gattrib by SDB.
318 *------------------------------------------------------------------*/
319 void s_object_delete_text_object_in_object(TOPLEVEL
*toplevel
,
322 s_delete(toplevel
, text_object
);
323 toplevel
->page_current
->CHANGED
= 1;
326 /* What does this do?!?!? Maybe I don't need it!!! */
327 toplevel
->page_current
->object_tail
=
328 return_tail(toplevel
->page_current
->object_head
);
334 /*------------------------------------------------------------------*/
335 /*! \brief This verifies that the object has a non-null symbol file.
337 * \returns It returns 0 = valid symbol file, 1 = no symbol file found.
339 *------------------------------------------------------------------*/
340 int s_object_has_sym_file(OBJECT
*object
)
344 filename
= object
->complex_basename
;
345 if (filename
!= NULL
) {
347 printf("In s_object_has_sym_file, object has sym file = %s.\n", filename
);
352 printf("In s_object_has_sym_file, found object with no attached symbol file.\n");