gsch2pcb: Make --m4-file and -m4-pcbdir arguments work again.
[geda-gaf/peter-b.git] / gattrib / src / s_object.c
blob8f25a03c1d37a914d3eb90e4adc7721d04f99fda
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 /*------------------------------------------------------------------*/
21 /*! \file
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
30 * fcns in libgeda.
33 #include <config.h>
35 #include <stdio.h>
36 #ifdef HAVE_STRING_H
37 #include <string.h>
38 #endif
39 #include <math.h>
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
50 #include <dmalloc.h>
51 #endif
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
67 * way:
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
71 * to attrib_graphic.
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.
80 void
81 s_object_add_comp_attrib_to_object (TOPLEVEL *toplevel,
82 OBJECT *o_current,
83 char *new_attrib_name,
84 char *new_attrib_value,
85 gint visibility,
86 gint show_name_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,
95 name_value_pair,
96 visibility,
97 show_name_value,
98 o_current);
101 return;
106 /*------------------------------------------------------------------*/
108 * \todo This needs to be filled in.
110 void
111 s_object_add_net_attrib_to_object (TOPLEVEL *toplevel,
112 OBJECT *o_current,
113 char *new_attrib_name,
114 char *new_attrib_value)
116 /* TBD */
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
125 * way:
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
129 * to attrib_graphic.
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
136 * pins???
138 void
139 s_object_add_pin_attrib_to_object (TOPLEVEL *toplevel,
140 OBJECT *o_current,
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,
150 name_value_pair,
151 INVISIBLE,
152 SHOW_NAME_VALUE,
153 o_current);
156 return;
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,
173 OBJECT *o_current,
174 char *new_attrib_name,
175 char *new_attrib_value,
176 gint visibility,
177 gint show_name_value)
179 GList *a_iter;
180 OBJECT *a_current;
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. */
209 } else {
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);
216 } /* while */
218 /* if we get here, it's because we have failed to find the attrib on the component.
219 * This is an error condition. */
220 fprintf(stderr,
221 "In s_object_replace_attrib_in_object, we have failed to find the attrib %s on the component. Exiting . . .\n",
222 new_attrib_name);
223 exit(-1);
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
236 void
237 s_object_remove_attrib_in_object (TOPLEVEL *toplevel,
238 OBJECT *o_current,
239 char *new_attrib_name)
241 GList *a_iter;
242 OBJECT *a_current;
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. */
260 #ifdef DEBUG
261 printf("In s_object_remove_attrib_in_object, removing attrib with name = %s\n", old_attrib_name);
262 #endif
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. */
279 fprintf(stderr,
280 "In s_object_remove_attrib_in_object, we have failed to find the attrib %s on the component. Exiting . . .\n",
281 new_attrib_name);
282 exit(-1);
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
294 * \param text_string
295 * \param visibility
296 * \param show_name_value
297 * \param object
298 * \returns pointer to the object
299 * \todo Does it need to return OBJECT?
301 OBJECT *
302 s_object_attrib_add_attrib_in_object (TOPLEVEL *toplevel,
303 char *text_string,
304 int visibility,
305 int show_name_value,
306 OBJECT * object)
308 int world_x = -1, world_y = -1;
309 int color;
310 int left, right, top, bottom;
311 OBJECT *o_current;
312 OBJECT *new_obj;
314 color = DETACHED_ATTRIBUTE_COLOR;
316 o_current = object;
318 /* creating a toplevel or unattached attribute */
319 if (o_current) {
320 /* get coordinates of where to place the text object */
321 switch (o_current->type) {
322 case (OBJ_COMPLEX):
323 world_x = o_current->complex->x;
324 world_y = o_current->complex->y;
325 color = ATTRIBUTE_COLOR;
326 break;
328 case (OBJ_NET):
329 world_x = o_current->complex->x;
330 world_y = o_current->complex->y;
331 color = ATTRIBUTE_COLOR;
332 break;
334 default:
335 fprintf(stderr, "In s_object_attrib_add_attrib_in_object, trying to add attrib to non-complex or non-net!\n");
336 exit(-1);
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 */
344 world_x = left;
345 world_y = top;
347 /* printf("%d %d\n", world_x, world_y); */
348 color = DETACHED_ATTRIBUTE_COLOR;
351 /* first create text item */
352 #if DEBUG
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);
359 #endif
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 */
371 if (o_current) {
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;
381 return new_obj;
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
396 void
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)
415 char *filename;
417 filename = object->complex_basename;
418 if (filename != NULL) {
419 #ifdef DEBUG
420 printf("In s_object_has_sym_file, object has sym file = %s.\n", filename);
421 #endif
422 return 0;
423 } else {
424 #ifdef DEBUG
425 printf("In s_object_has_sym_file, found object with no attached symbol file.\n");
426 #endif
427 return 1;