1 /* Lepton EDA attribute editor
2 * Copyright (C) 2003-2010 Stuart D. Brorson.
3 * Copyright (C) 2003-2016 gEDA Contributors
4 * Copyright (C) 2017-2021 Lepton EDA Contributors
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 /*------------------------------------------------------------------*/
22 /*! \file
23 * \brief Functions for manipulating LeptonObjects.
24 *
25 * This file holds functions involved in manipulating the
26 * LeptonObject data structure. LeptonObject is defined in
27 * libgeda. An LeptonObject is a graphical primitive normally
28 * used in gschem. Example LeptonObjects: some text, a component, a
29 * pin, a line, etc.
30 *
31 * The functions herein are functions which I wrote as wrappers to the
32 * fcns in libgeda.
33 */
34
35 #include <config.h>
36
37 #include <stdio.h>
38 #ifdef HAVE_STRING_H
39 #include <string.h>
40 #endif
41 #include <math.h>
42
43 /*------------------------------------------------------------------
44 * Gattrib specific includes
45 *------------------------------------------------------------------*/
46 #include <liblepton/liblepton.h>
47 #include "../include/struct.h" /* typdef and struct declarations */
48 #include "../include/prototype.h" /* function prototypes */
49 #include "../include/globals.h"
50 #include "../include/gettext.h"
51
52
53 /*------------------------------------------------------------------
54 * Gattrib specific defines
55 *------------------------------------------------------------------*/
56 #define DEFAULT_TEXT_SIZE 10
57
58 static LeptonObject*
59 s_object_attrib_add_attrib_in_object (LeptonPage *active_page,
60 char *text_string,
61 gint visibility,
62 gint show_name_value,
63 LeptonObject * object);
64
65 /* =================== Public Functions ====================== */
66
67 /*------------------------------------------------------------------*/
68 /*! \brief Add an attribute to an LeptonObject
69 *
70 * This fcn adds a new attrib to o_current, when o_current is a
71 * component. It does it in the following
72 * way:
73 * -# It creates an object -- "attrib_graphic" -- and fills it in.
74 * -# It gets the position info from o_current's refdes attrib and
75 * calls o_text_new() to add position info and name=value string
76 * to attrib_graphic.
77 * -# It calls o_attrib_add() to wrap attrib_graphic with (attribute LeptonObject )
78 * \param toplevel LeptonToplevel structure
79 * \param o_current pointer to object to add attribute to
80 * \param new_attrib_name name of the attribute to add
81 * \param new_attrib_value value of the attribute to add
82 * \param visibility Is the attribute visible?
83 * \param show_name_value Control visibility of name and value.
84 */
85 void
s_object_add_comp_attrib_to_object(LeptonToplevel * toplevel,LeptonObject * o_current,char * new_attrib_name,char * new_attrib_value,gint visibility,gint show_name_value)86 s_object_add_comp_attrib_to_object (LeptonToplevel *toplevel,
87 LeptonObject *o_current,
88 char *new_attrib_name,
89 char *new_attrib_value,
90 gint visibility,
91 gint show_name_value)
92 {
93 LeptonPage *active_page = NULL;
94 char *name_value_pair;
95 g_return_if_fail (o_current != NULL);
96
97 active_page = lepton_toplevel_get_page_current (toplevel);
98
99 /* One last sanity check, then add attrib */
100 if (strlen(new_attrib_value) != 0) {
101 name_value_pair = g_strconcat(new_attrib_name, "=", new_attrib_value, NULL);
102 s_object_attrib_add_attrib_in_object (active_page,
103 name_value_pair,
104 visibility,
105 show_name_value,
106 o_current);
107 }
108
109 return;
110
111 }
112
113
114 /*------------------------------------------------------------------*/
115 /*!
116 * \todo This needs to be filled in.
117 */
118 void
s_object_add_net_attrib_to_object(LeptonToplevel * toplevel,LeptonObject * o_current,char * new_attrib_name,char * new_attrib_value)119 s_object_add_net_attrib_to_object (LeptonToplevel *toplevel,
120 LeptonObject *o_current,
121 char *new_attrib_name,
122 char *new_attrib_value)
123 {
124 /* TBD */
125 }
126
127
128 /*------------------------------------------------------------------*/
129 /*! \brief Add a new attribute to an pin LeptonObject
130 *
131 * Add a new attribute to o_current, when o_current is a
132 * pin. It does it in the following
133 * way:
134 * -# It creates an object -- "attrib_graphic" -- and fills it in.
135 * -# It gets the position info from o_current's refdes attrib and
136 * calls o_text_new() to add position info and name=value string
137 * to attrib_graphic.
138 * -# It calls o_attrib_add() to wrap attrib_graphic with (attribute
139 LeptonObject)
140 * \param toplevel LeptonToplevel structure
141 * \param o_current Pointer to pin object
142 * \param new_attrib_name Name of attribute to add
143 * \param new_attrib_value Value of attribute to add
144 * \todo Do I really need separate fcns for comps, nets, and
145 * pins???
146 */
147 void
s_object_add_pin_attrib_to_object(LeptonToplevel * toplevel,LeptonObject * o_current,char * new_attrib_name,char * new_attrib_value)148 s_object_add_pin_attrib_to_object (LeptonToplevel *toplevel,
149 LeptonObject *o_current,
150 char *new_attrib_name,
151 char *new_attrib_value)
152 {
153 LeptonPage *active_page = NULL;
154 char *name_value_pair;
155 g_return_if_fail (o_current != NULL);
156
157 active_page = lepton_toplevel_get_page_current (toplevel);
158
159 /* One last sanity check */
160 if (strlen(new_attrib_value) != 0) {
161 name_value_pair = g_strconcat(new_attrib_name, "=", new_attrib_value, NULL);
162 s_object_attrib_add_attrib_in_object (active_page,
163 name_value_pair,
164 INVISIBLE,
165 SHOW_NAME_VALUE,
166 o_current);
167 }
168
169 return;
170 }
171
172
173 /*------------------------------------------------------------------*/
174 /*! \brief Replace attribute value in object
175 *
176 * Find the instance of attrib_name on o_current, and
177 * replace its value with the new_attrib_value.
178 *
179 * \param o_current object to operate on
180 * \param new_attrib_name name of attribute to replace
181 * \param new_attrib_value value to set attribute to
182 * \param visibility set visibility of attribute
183 * \param show_name_value set visibility of attribute name and value
184 */
185 void
s_object_replace_attrib_in_object(LeptonObject * o_current,char * new_attrib_name,char * new_attrib_value,gint visibility,gint show_name_value)186 s_object_replace_attrib_in_object(LeptonObject *o_current,
187 char *new_attrib_name,
188 char *new_attrib_value,
189 gint visibility,
190 gint show_name_value)
191 {
192 GList *a_iter;
193 LeptonObject *a_current;
194 char *old_attrib_text;
195 char *old_attrib_name;
196 char *new_attrib_text;
197
198
199 a_iter = lepton_object_get_attribs (o_current);
200 while (a_iter != NULL) {
201 a_current = (LeptonObject*) a_iter->data;
202 if (lepton_object_is_text (a_current)
203 && a_current->text != NULL) { /* found an attribute */
204
205 /* may need to check more thoroughly here. . . . */
206 old_attrib_text = g_strdup (lepton_text_object_get_string (a_current));
207 old_attrib_name = u_basic_breakup_string(old_attrib_text, '=', 0);
208
209 if (strcmp(old_attrib_name, new_attrib_name) == 0) {
210 /* create attrib=value text string */
211 new_attrib_text = g_strconcat(new_attrib_name, "=", new_attrib_value, NULL);
212 lepton_text_object_set_string (a_current, new_attrib_text);
213 if (visibility != LEAVE_VISIBILITY_ALONE)
214 lepton_text_object_set_visibility (a_current, visibility);
215 if (show_name_value != LEAVE_NAME_VALUE_ALONE)
216 lepton_text_object_set_show (a_current, show_name_value);
217 g_free(new_attrib_text);
218 g_free(old_attrib_text);
219 g_free(old_attrib_name);
220 return; /* we are done -- leave. */
221 } else {
222 g_free(old_attrib_text);
223 g_free(old_attrib_name);
224 } /* if (strcmp . . . . */
225 } /* if (a_current . . . . */
226
227 a_iter = g_list_next (a_iter);
228 } /* while */
229
230 /* if we get here, it's because we have failed to find the attrib on the component.
231 * This is an error condition. */
232 fprintf (stderr, "s_object_replace_attrib_in_object: ");
233 fprintf (stderr,
234 _("Failed to find the attrib %1$s on the component.\n"),
235 new_attrib_name);
236 exit(-1);
237 }
238
239
240 /*------------------------------------------------------------------*/
241 /*!
242 * \brief Remove attribute from object
243 *
244 * Remove an attribute from an object.
245 * \param toplevel LeptonToplevel structure
246 * \param o_current Object to remove attribute from
247 * \param new_attrib_name Name of attribute to remove
248 */
249 void
s_object_remove_attrib_in_object(LeptonToplevel * toplevel,LeptonObject * o_current,char * new_attrib_name)250 s_object_remove_attrib_in_object (LeptonToplevel *toplevel,
251 LeptonObject *o_current,
252 char *new_attrib_name)
253 {
254 GList *a_iter;
255 LeptonObject *a_current;
256 LeptonObject *attribute_object;
257 char *old_attrib_text;
258 char *old_attrib_name;
259
260 a_iter = lepton_object_get_attribs (o_current);
261 while (a_iter != NULL) {
262 a_current = (LeptonObject*) a_iter->data;
263 if (lepton_object_is_text (a_current)
264 && a_current->text != NULL) { /* found an attribute */
265
266 /* may need to check more thoroughly here. . . . */
267 old_attrib_text = g_strdup (lepton_text_object_get_string (a_current));
268 old_attrib_name = u_basic_breakup_string(old_attrib_text, '=', 0);
269
270 if (strcmp(old_attrib_name, new_attrib_name) == 0) {
271 /* We've found the attrib. Delete it and then return. */
272
273 g_debug ("s_object_remove_attrib_in_object: "
274 "Removing attrib with name = %1$s\n", old_attrib_name);
275
276 attribute_object = a_current;
277 s_object_delete_text_object_in_object (toplevel, attribute_object);
278
279 g_free(old_attrib_text);
280 g_free(old_attrib_name);
281 return; /* we are done -- leave. */
282 }
283 g_free(old_attrib_text);
284 g_free(old_attrib_name);
285 }
286 a_iter = g_list_next (a_iter);
287 }
288
289 /* if we get here, it's because we have failed to find the attrib on the component.
290 * This is an error condition. */
291 fprintf (stderr, "s_object_remove_attrib_in_object: ");
292 fprintf (stderr,
293 _("Failed to find the attrib %1$s on the component.\n"),
294 new_attrib_name);
295 exit(-1);
296 }
297
298
299
300 /*------------------------------------------------------------------*/
301 /*! \brief Attach attribute to object.
302 *
303 * Attach the name=value pair to the LeptonObject "object". This function
304 * was stolen from gschem/src/o_attrib.c:o_attrib_add_attrib and
305 * hacked for gattrib.
306 * \param toplevel LeptonToplevel to operate on
307 * \param text_string
308 * \param visibility
309 * \param show_name_value
310 * \param o_current
311 * \returns pointer to the object
312 * \todo Does it need to return LeptonObject?
313 */
314 static LeptonObject *
s_object_attrib_add_attrib_in_object(LeptonPage * active_page,char * text_string,int visibility,int show_name_value,LeptonObject * o_current)315 s_object_attrib_add_attrib_in_object (LeptonPage *active_page,
316 char *text_string,
317 int visibility,
318 int show_name_value,
319 LeptonObject * o_current)
320 {
321 int world_x = -1, world_y = -1;
322 int color;
323 LeptonObject *new_obj;
324
325 g_return_val_if_fail ((o_current != NULL), NULL);
326
327 /* creating a toplevel or unattached attribute */
328 /* get coordinates of where to place the text object */
329 switch (lepton_object_get_type (o_current)) {
330 case (OBJ_COMPONENT):
331 world_x = lepton_component_object_get_x (o_current);
332 world_y = lepton_component_object_get_y (o_current);
333 color = ATTRIBUTE_COLOR;
334 break;
335
336 case (OBJ_NET):
337 world_x = lepton_component_object_get_x (o_current);
338 world_y = lepton_component_object_get_y (o_current);
339 color = ATTRIBUTE_COLOR;
340 break;
341
342 default:
343 fprintf (stderr, "s_object_attrib_add_attrib_in_object: ");
344 fprintf (stderr, _("Trying to add attrib to non-component or non-net!\n"));
345 exit(-1);
346 }
347
348 /* first create text item */
349 g_debug ("s_object_attrib_add_attrib_in_object: "
350 "About to attach new text attrib with properties:\n"
351 " color = %d\n"
352 " text_string = %s\n"
353 " visibility = %d\n"
354 " show_name_value = %d\n",
355 color, text_string, visibility, show_name_value);
356
357 new_obj = lepton_text_object_new (color,
358 world_x,
359 world_y,
360 LOWER_LEFT,
361 0, /* zero is angle */
362 text_string,
363 DEFAULT_TEXT_SIZE,
364 visibility,
365 show_name_value);
366 lepton_page_append (active_page, new_obj);
367
368 /* Now the current active page contains the new text item. */
369
370 /* now attach the attribute to the object */
371 /* remember that o_current contains the object to get the attribute */
372 o_attrib_attach (new_obj, o_current, FALSE);
373
374 lepton_page_set_changed (active_page, 1);
375
376 return new_obj;
377 }
378
379
380
381
382 /*------------------------------------------------------------------*/
383 /*! \brief Delete text object
384 *
385 * Delete the text object pointed to by text_object. This function
386 * was shamelessly stolen from gschem/src/o_delete.c and hacked
387 * for gattrib by SDB.
388 * \param toplevel LeptonToplevel to be operated on
389 * \param test_object text object to be deleted
390 */
391 void
s_object_delete_text_object_in_object(LeptonToplevel * toplevel,LeptonObject * text_object)392 s_object_delete_text_object_in_object (LeptonToplevel *toplevel,
393 LeptonObject * text_object)
394 {
395 LeptonPage *active_page = lepton_toplevel_get_page_current (toplevel);
396 lepton_object_delete (text_object);
397 lepton_page_set_changed (active_page, 1);
398 }
399
400
401 /*------------------------------------------------------------------*/
402 /*! \brief Ensure object has a symbol file
403 *
404 * This verifies that the object has a non-null symbol file.
405 *
406 * \returns 0 = valid symbol file, 1 = no symbol file found.
407 */
s_object_has_sym_file(LeptonObject * object)408 int s_object_has_sym_file(LeptonObject *object)
409 {
410 char *filename;
411
412 filename = lepton_component_object_get_basename (object);
413 if (filename != NULL) {
414 g_debug ("s_object_has_sym_file: Object has sym file = %s.\n", filename);
415 return 0;
416 } else {
417 g_debug ("s_object_has_sym_file: Found object with no attached symbol file.\n");
418 return 1;
419 }
420 }
421