Prefer o_text_change over random poking.
[geda-gaf/berndj.git] / gattrib / src / s_object.c
blob3c3171e8a8c1b17c5c9b3f8a19ec3df4d8fa1b28
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
27 * fcns in libgeda.
28 *------------------------------------------------------------------ */
30 #include <config.h>
32 #include <stdio.h>
33 #ifdef HAVE_STRING_H
34 #include <string.h>
35 #endif
36 #include <math.h>
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
47 #include <dmalloc.h>
48 #endif
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
62 * way:
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
66 * to attrib_graphic.
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,
73 gint visibility,
74 gint show_name_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);
85 return;
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)
96 /* TBD */
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
103 * way:
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
107 * to attrib_graphic.
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
110 * pins???
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);
125 return;
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,
136 gint visibility,
137 gint show_name_value)
139 GList *a_iter;
140 OBJECT *a_current;
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. */
161 } else {
162 g_free(old_attrib_name);
163 } /* if (strcmp . . . . */
164 } /* if (a_current . . . . */
166 a_iter = g_list_next (a_iter);
167 } /* while */
169 /* if we get here, it's because we have failed to find the attrib on the component.
170 * This is an error condition. */
171 fprintf(stderr,
172 "In s_object_replace_attrib_in_object, we have failed to find the attrib %s on the component. Exiting . . .\n",
173 new_attrib_name);
174 exit(-1);
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)
184 GList *a_iter;
185 OBJECT *a_current;
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. */
202 if (GEDA_DEBUG) {
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. */
219 fprintf(stderr,
220 "In s_object_remove_attrib_in_object, we have failed to find the attrib %s on the component. Exiting . . .\n",
221 new_attrib_name);
222 exit(-1);
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,
234 char *text_string,
235 int visibility,
236 int show_name_value,
237 OBJECT * object)
239 int world_x = -1, world_y = -1;
240 int color;
241 int left, right, top, bottom;
242 OBJECT *o_current;
243 OBJECT *new_obj;
245 color = toplevel->detachedattr_color;
247 o_current = object;
249 /* creating a toplevel or unattached attribute */
250 if (o_current) {
251 /* get coordinates of where to place the text object */
252 switch (o_current->type) {
253 case (OBJ_COMPLEX):
254 world_x = o_current->complex->x;
255 world_y = o_current->complex->y;
256 color = toplevel->attribute_color;
257 break;
259 case (OBJ_NET):
260 world_x = o_current->complex->x;
261 world_y = o_current->complex->y;
262 color = toplevel->attribute_color;
263 break;
265 default:
266 fprintf(stderr, "In s_object_attrib_add_attrib_in_object, trying to add attrib to non-complex or non-net!\n");
267 exit(-1);
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 */
274 world_x = left;
275 world_y = top;
277 /* printf("%d %d\n", world_x, world_y); */
278 color = toplevel->detachedattr_color;
281 /* first create text item */
282 if (GEDA_DEBUG) {
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 */
300 if (o_current) {
301 o_attrib_attach(toplevel, toplevel->page_current->object_tail,
302 o_current);
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,
320 OBJECT *text_object)
322 s_delete(toplevel, text_object);
323 toplevel->page_current->CHANGED = 1;
325 #if 0
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);
329 #endif
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)
342 char *filename;
344 filename = object->complex_basename;
345 if (filename != NULL) {
346 if (GEDA_DEBUG) {
347 printf("In s_object_has_sym_file, object has sym file = %s.\n", filename);
349 return 0;
350 } else {
351 if (GEDA_DEBUG) {
352 printf("In s_object_has_sym_file, found object with no attached symbol file.\n");
354 return 1;