1 /* gEDA - GPL Electronic Design Automation
2 * libgeda - gEDA's library
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 gEDA Contributors (see ChangeLog for details)
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111 USA
37 #include "../include/prototype.h"
39 #ifdef HAVE_LIBDMALLOC
43 /*! Basic string splitting delimiters */
44 #define DELIMITERS ",; "
47 * No special type for attributes
48 * You can only edit text attributes
50 * be sure in o_copy o_move o_delete you maintain the attributes
51 * delete is a bare, because you will have to unattach the other end
52 * and in o_save o_read as well
53 * and in o_select when selecting objects, select the attributes
55 * \todo there needs to be a modifier (in struct.h, such as a flag) which
56 * signifies that this is an attribute (really? why?)
59 * return pointer from attrib_list
62 /*! \brief Update an attribute's uref.
63 * \par Function Description
64 * Update an attribute's uref.
66 * \param [in] w_current The TOPLEVEL object
67 * \param [in] o_current The object to update.
70 * Martin Benes' auto uref renumber code
72 void o_attrib_update_urefBM (TOPLEVEL
*w_current
, OBJECT
*o_current
)
74 OBJECT
*list_head
,*obj
;
76 int i
= -1, name_conflict
,len
;
80 if (strncmp(o_current
->text
->string
,"uref=",5)) /* deprecated */
83 len
=strlen(o_current
->text
->string
);
84 uref
=g_malloc(len
+10);
85 strcpy(uref
,o_current
->text
->string
);
87 while (o_current
->text
->string
[len
-1]<='9' &&
88 o_current
->text
->string
[len
-1]>='0')
91 list_head
=return_head(o_current
);
92 for (obj
=list_head
->next
;obj
;obj
=obj
->next
) {
93 if (obj
->type
==OBJ_TEXT
&& obj
->attribute
)
97 index_list
=calloc(index_list_len
,1); /* convert to g_new maybe... */
100 for (obj
=list_head
->next
;obj
;obj
=obj
->next
) {
101 if (obj
->type
==OBJ_TEXT
&& obj
->attribute
&& obj
!=o_current
) {
102 if (strncmp(uref
,obj
->text
->string
,len
)==0) {
103 if (strcmp(uref
+len
,obj
->text
->string
+len
)==0) {
106 i
=atoi(obj
->text
->string
+len
);
107 if (i
<index_list_len
)
114 for (i
=0;index_list
[i
];++i
);
115 sprintf(uref
+len
,"%d", i
);
116 g_free(o_current
->text
->string
);
117 o_current
->text
->string
=uref
;
118 o_text_recreate(w_current
, o_current
);
124 /*! \brief Search for an item in an attribute list.
125 * \par Function Description
126 * Search for an item in an attribute list.
128 * \param [in] list ATTRIB pointer to the list to be searched.
129 * \param [in] item item to be found.
131 ATTRIB
*o_attrib_search(ATTRIB
*list
, OBJECT
*item
)
141 while(a_current
!= NULL
) {
142 if (a_current
->object
!= NULL
) {
143 if (item
->sid
== a_current
->object
->sid
) {
148 a_current
= a_current
->next
;
154 /*! \brief Get the last attribute in the list.
155 * \par Function Description
156 * Get the last attribute in the list.
158 * \param [in] head ATTRIB pointer to beginning of list.
159 * \return Returns an ATTRIB pointer to the last attribute in the list.
161 ATTRIB
*o_attrib_return_tail(ATTRIB
*head
)
163 ATTRIB
*a_current
=NULL
;
164 ATTRIB
*current
=NULL
;
167 while ( a_current
!= NULL
) { /* goto end of list */
169 a_current
= a_current
->next
;
174 /*! \brief Create an attribute list head item.
175 * \par Function Description
176 * Create an attribute list head item.
178 * \param [in] parent OBJECT pointer that will become the parent
179 * of this new head item.
180 * \return Returns an ATTRIB pointer to the newly created head item.
182 * \todo Rename this function to be consistant.
184 ATTRIB
*add_attrib_head(OBJECT
*parent
)
188 head
= (ATTRIB
*) g_malloc(sizeof(ATTRIB
));
191 /* highly experimental hack */
192 head
->object
= parent
;
193 head
->copied_to
= NULL
;
197 * why the grief? well everywhere a attribute is refered to
198 * you have to skip over the head, you really ought to robustify
199 * all references to this object pointer when talking to attributes
200 * hack of course I think this is okay now though
206 /*! \brief Add an attribute to an existing attribute list.
207 * \par Function Description
208 * Add an attribute to an existing attribute list.
210 * \param [in] w_current The TOPLEVEL object.
211 * \param [in,out] list_head The list where you want to add item to.
212 * \param [in] item The item you want to add as an attribute.
213 * \return An ATTRIB pointer to the newly created attribute.
215 ATTRIB
*o_attrib_add(TOPLEVEL
*w_current
, ATTRIB
*list_head
, OBJECT
*item
)
220 /* get tail of list_head */
221 end
= o_attrib_return_tail(list_head
);
223 /* create an new st_attrib object */
224 new = (ATTRIB
*) g_malloc(sizeof(ATTRIB
));
226 /* fill item with correct data (mainly item) */
230 new->copied_to
= NULL
;
231 new->object
->attribute
= 1; /* Set the attribute to true, hack define */
232 /* Show that that item is an attribute */
233 new->object
->color
= w_current
->attribute_color
;
235 if (new->object
->type
== OBJ_TEXT
) {
236 o_complex_set_color(new->object
->text
->prim_objs
,
238 } else if (new->object
->type
== OBJ_COMPLEX
||
239 new->object
->type
== OBJ_PLACEHOLDER
) {
240 o_complex_set_color(new->object
->complex->prim_objs
,
244 /* Add link from item to attrib listing */
245 new->object
->attached_to
= new;
247 /* set next of tail of end->attrib to item */
256 /*! \brief Free single item in attribute list.
257 * \par Function Description
258 * Free single item in attribute list.
260 * \param [in] w_current The TOPLEVEL object.
261 * \param [in] current ATTRIB pointer to free.
264 * this routine is not nice to next and prev
265 * this routine is only called from free_all
267 void o_attrib_free(TOPLEVEL
*w_current
, ATTRIB
*current
)
269 if (current
!= NULL
) {
271 /* \todo this makes me nervous... very nervous */
272 if (current
->object
!= NULL
&& current
->prev
!= NULL
) {
273 current
->object
->attribute
= 0;
274 current
->object
->attached_to
=NULL
;
275 current
->object
->color
= w_current
->detachedattr_color
;
277 if (current
->object
->type
== OBJ_TEXT
) {
278 o_complex_set_color(current
->object
->text
->prim_objs
,
279 current
->object
->color
);
281 printf("Tried to set the color on a complex!\nlibgeda/src/o_attrib_free 1\n");
284 /* \todo not sure on this */
285 if (current
->object
->saved_color
!= -1) {
286 if (current
->object
->type
== OBJ_TEXT
) {
287 o_complex_set_saved_color_only(
288 current
->object
->text
->prim_objs
,
289 w_current
->detachedattr_color
);
291 printf("Tried to set the color on a complex!\nlibgeda/src/o_attrib_free 2\n");
293 current
->object
->saved_color
= w_current
->
298 /* \todo were do we detach the object->attached_to? above */
299 current
->object
=NULL
;
306 /*! \brief Attach existing attribute to an object.
307 * \par Function Description
308 * Attach existing attribute to an object.
310 * \param [in] w_current The TOPLEVEL object.
311 * \param [in] parent_list List where actual attribute objects live.
312 * \param [in] text_object The attribute to be added.
313 * \param [out] object The object where you want to add item as an attribute.
316 * Lists first then specific single item.
319 * typically parent_list is object_parent (object_head), but it is
320 * overridden in o_complex_add so that it points to head node of the complex
323 void o_attrib_attach(TOPLEVEL
*w_current
, OBJECT
*parent_list
,
324 OBJECT
*text_object
, OBJECT
*object
)
326 OBJECT
*o_current
= NULL
;
328 ATTRIB
*found
= NULL
;
329 OBJECT
*found2
= NULL
; /* object in main list */
331 o_current
= text_object
;
333 if (object
== NULL
) {
334 printf("ah.. object was not found in the parent list!\n");
338 /* is the object already part of the list ? */
339 found
= o_attrib_search(object
->attribs
, o_current
);
340 if (!found
) { /* no it's not, add it to the list */
342 found2
= (OBJECT
*) o_list_search(parent_list
, o_current
);
344 /* check to see if found2 is not null hack */
346 if (found2
->type
== OBJ_TEXT
) {
348 if (object
->attribs
== NULL
) {
350 add_attrib_head(object
);
354 if (found2
->attached_to
) {
355 fprintf(stderr
, "You cannot attach this attribute [%s] to more than one object\n", found2
->text
->string
);
358 o_attrib_add(w_current
,
362 o_current
->color
= w_current
->
366 o_current
->text
->prim_objs
,
369 if (o_current
->saved_color
!= -1) {
370 o_complex_set_saved_color_only(
371 o_current
->text
->prim_objs
,
373 o_current
->saved_color
=
376 /* can't do this here since just selecting something */
377 /* will cause this to be set */
378 /* w_current->page_current->CHANGED=1;*/
381 o_attrib_update_urefBM (w_current
, o_current
);
385 fprintf(stderr
, "You cannot attach non text items as attributes!\n");
389 if (o_current
->text
->string
) {
390 printf("Attribute [%s] already attached\n",
391 o_current
->text
->string
);
396 /*! \todo Empty function.
398 * \par Function Description
400 * \param [in] w_current The TOPLEVEL object.
405 o_attrib_detach_test(TOPLEVEL
*w_current
, OBJECT
*list
, OBJECT
*items
)
408 /* this all needs to be rethought out */
409 /* loop over items till NULL */
410 /* Search for item in object->attrib */
411 /* o_attrib_search(list->attribs, current_item) */
413 /*call o_attrib_remove(object->attributes, current_item->attrib_struct);*/
419 /*! \todo Empty function.
421 * \par Function Description
426 /* only can edit a text, special case of edit text */
427 void o_attrib_edit(OBJECT
*list
, OBJECT
*item
)
432 /*! \todo Empty function.
434 * \par Function Description
439 * should this be st_attrib or st_object?
441 void o_attrib_select_draw(ATTRIB
*list
)
445 /* or a white bounding box? */
448 /*! \todo Empty function.
450 * \par Function Description
455 * should this be st_attrib or st_object?
457 void o_attrib_unselect_draw(ATTRIB
*list
)
461 /* or a white bounding box? */
465 /*! \brief Free all attribute items in a list.
466 * \par Function Description
467 * Free all attribute items in a list.
469 * \param [in] w_current The TOPLEVEL object.
470 * \param [in,out] list The list to free.
473 * this routine uses o_attrib_free (which isn't nice to next, prev)
474 * so it should only be used when an object is being destroyed
477 void o_attrib_free_all(TOPLEVEL
*w_current
, ATTRIB
*list
)
484 while (a_current
!= NULL
) {
485 a_next
= a_current
->next
;
486 o_attrib_free(w_current
, a_current
);
491 /*! \brief Print all attributes to a Postscript document.
492 * \par Function Description
493 * Print all attributes to a Postscript document.
495 * \param [in] attributes List of attributes to print.
497 void o_attrib_print(ATTRIB
*attributes
)
501 a_current
= attributes
;
503 while (a_current
!= NULL
) {
504 printf("Attribute points to: %s\n", a_current
->object
->name
);
505 if (a_current
->object
&& a_current
->object
->text
) {
506 printf("\tText is: %s\n", a_current
->object
->text
->string
);
509 if (!a_current
->object
) {
510 printf("oops found a null attrib object\n");
512 a_current
= a_current
->next
;
516 /*! \brief Print all attributes in reverse order to a Postscript document.
517 * \par Function Description
518 * Print all attributes in reverse order to a Postscript document.
520 * \param [in] attributes List of attributes to print.
522 void o_attrib_print_reverse(ATTRIB
*attributes
)
526 a_current
= o_attrib_return_tail(attributes
);
528 while (a_current
!= NULL
) {
529 printf("Attribute points to: %s\n", a_current
->object
->name
);
530 if (a_current
->object
&& a_current
->object
->text
) {
531 printf("\tText is: %s\n", a_current
->object
->text
->string
);
534 if (!a_current
->object
) {
535 printf("oops found a null attrib object\n");
537 a_current
= a_current
->prev
;
541 /*! \todo Empty function.
543 * \par Function Description
545 * \param [in] list The attribute list to copy.
546 * \return Always NULL.
549 * very hard, I don't think we need it though
551 ATTRIB
*o_attrib_copy(ATTRIB
*list
)
556 /*! \brief Delete an attribute.
557 * \par Function Description
558 * This function goes out and removes the current attribute,
559 * while preserving the next, prev pointers.
560 * This function should be used when detaching an attribute.
562 * \param [in] a_current The attribute to be deleted.
564 void o_attrib_delete(ATTRIB
*a_current
)
566 if (a_current
!= NULL
) {
569 a_current
->next
->prev
= a_current
->prev
;
571 a_current
->next
= NULL
;
574 a_current
->prev
->next
= a_current
->next
;
576 a_current
->prev
= NULL
;
578 if (a_current
->object
) {
579 a_current
->object
->attribute
=0;
580 a_current
->object
->attached_to
=NULL
;
582 a_current
->object
= NULL
;
588 /*! \todo Finish function.
589 * \brief Remove an attribute item from an attribute list.
590 * \par Function Description
591 * This function goes out and removes an attribute from a list.
592 * It searches for the attribute and then removes it using the
593 * good #o_attrib_delete() routine.
595 * \param [in] list ATTRIB list to remove attribute from.
596 * \param [in] remove The ATTRIB to remove from list.
599 * This function is the detach_all routine.
600 * It is not currently being used.
601 * It is not even done.
603 void o_attrib_remove(ATTRIB
*list
, ATTRIB
*remove
)
609 while (a_current
!= NULL
) {
611 if (a_current
== remove
) {
614 a_current
= a_current
->next
;
618 /*! \todo Is this function used?
620 * \brief Detach all attributes from a list.
621 * \par Function Description
622 * Detach all attributes from a list.
624 * \param [in] w_current The TOPLEVEL object.
625 * \param [in] object_list Attribute list to delete.
626 * \param [in] main_head The head of the attribute list.
628 void o_attrib_detach_all(TOPLEVEL
*w_current
, OBJECT
*object_list
, OBJECT
*main_head
)
631 OBJECT
*o_current
=NULL
;
633 o_current
= object_list
;
635 while(o_current
!= NULL
) {
637 X
= (OBJECT
*) o_list_search(main_head
, o_current
);
640 if (X
->attribs
!= NULL
) {
641 o_attrib_free_all(w_current
, X
->attribs
);
642 X
->attribs
= NULL
; /* leak possible? */
643 w_current
->page_current
->CHANGED
=1;
646 o_current
= o_current
->next
;
651 /*! \brief Read attributes from a buffer.
652 * \par Function Description
653 * Read attributes from a TextBuffer.
655 * \param [in] w_current The TOPLEVEL object.
656 * \param [out] object_to_get_attribs Storage for attributes.
657 * \param [in] tb The text buffer to read from.
658 * \param [in] release_ver libgeda release version number.
659 * \param [in] fileformat_ver file format version number.
660 * \return Pointer to object_to_get_attribs.
662 OBJECT
*o_read_attribs(TOPLEVEL
*w_current
,
663 OBJECT
*object_to_get_attribs
,
665 unsigned int release_ver
, unsigned int fileformat_ver
)
667 OBJECT
*object_list
=NULL
;
671 int saved_color
= -1;
673 object_list
= object_to_get_attribs
;
677 line
= s_textbuffer_next_line (tb
);
678 if (line
== NULL
) break;
680 sscanf(line
, "%c", &objtype
);
684 object_list
= (OBJECT
*) o_line_read(w_current
,
687 release_ver
, fileformat_ver
);
692 object_list
= (OBJECT
*) o_net_read(w_current
,
695 release_ver
, fileformat_ver
);
699 object_list
= (OBJECT
*) o_bus_read(w_current
,
702 release_ver
, fileformat_ver
);
706 object_list
= (OBJECT
*) o_box_read(w_current
,
709 release_ver
, fileformat_ver
);
713 object_list
= (OBJECT
*) o_circle_read(
717 release_ver
, fileformat_ver
);
721 case(OBJ_PLACEHOLDER
):
723 object_list
= (OBJECT
*) o_complex_read(
727 release_ver
, fileformat_ver
);
729 /* this is necessary because complex may add
730 attributes which float */
732 object_list
= (OBJECT
*) return_tail(
737 object_list
= (OBJECT
*) o_pin_read(w_current
,
740 release_ver
, fileformat_ver
);
744 object_list
= (OBJECT
*) o_arc_read(w_current
,
747 release_ver
, fileformat_ver
);
751 line
= g_strdup (line
);
752 object_list
= (OBJECT
*) o_text_read(w_current
,
756 release_ver
, fileformat_ver
);
758 saved_color
= object_list
->color
;
763 case(ENDATTACH_ATTR
):
770 o_attrib_attach(w_current
,
771 w_current
->page_current
->object_parent
,
772 object_list
, object_to_get_attribs
);
773 /* check color to set it to the right value */
774 if (object_list
->color
!= saved_color
) {
775 object_list
->color
= saved_color
;
777 if (object_list
->type
== OBJ_TEXT
) {
779 object_list
->text
->prim_objs
,
782 printf("Tried to set the color on a complex in libgeda/src/o_read_attribs\n");
787 fprintf(stderr
, "Tried to attach a non-text item as an attribute\n");
793 /*! \brief Save attributes to a file.
794 * \par Function Description
795 * Save attributes to a file.
797 * \param [in] fp FILE pointer to write attributes to.
798 * \param [in] attribs attributes to write.
800 * this should be trimmed down to only save attributes which are text items
802 void o_save_attribs(FILE *fp
, ATTRIB
*attribs
)
804 ATTRIB
*a_current
=NULL
;
805 OBJECT
*o_current
=NULL
;
812 while ( a_current
!= NULL
) {
814 o_current
= a_current
->object
;
816 if (o_current
->type
!= OBJ_HEAD
) {
819 printf("type: %d %c ref: %d %c\n", o_current
->type
, o_current
->type
,
823 switch (o_current
->type
) {
826 out
= (char *) o_line_save(o_current
);
830 out
= (char *) o_net_save(o_current
);
834 out
= (char *) o_bus_save(o_current
);
838 out
= (char *) o_box_save(o_current
);
842 out
= (char *) o_circle_save(o_current
);
846 case(OBJ_PLACEHOLDER
): /* new type -- SDB 1.20.2005 */
847 out
= (char *) o_complex_save(o_current
);
851 out
= (char *) o_text_save(o_current
);
855 out
= (char *) o_pin_save(o_current
);
859 out
= (char *) o_arc_save(o_current
);
863 out
= (char *) o_picture_save(o_current
);
867 fprintf(stderr
, "Error type!\n");
871 /* output the line */
872 fprintf(fp
, "%s\n", out
);
875 a_current
= a_current
->next
;
881 /*! \brief Get name and value from name=value attribute.
882 * \par Function Description
883 * Get name and value from a name=value attribute.
885 * \param [in] string String to split into name/value pair.
886 * \param [out] name_ptr Name if found in string, NULL otherwise.
887 * \param [out] value_ptr Value if found in string, NULL otherwise.
888 * \return TRUE if string had equals in it, FALSE otherwise.
891 * both name and value must be pre allocated
892 * And if you get an invalid attribute (improper) with a name and no
893 * value, then it is NOT an attribute.
894 * Also, there cannot be any spaces beside the equals sign
895 * Changed: now it allocates memory for name and value strings.
897 * Caller must g_free these strings when not needed.
899 int o_attrib_get_name_value(char *string
, char **name_ptr
, char **value_ptr
)
904 if (name_ptr
== NULL
|| value_ptr
== NULL
) {
908 *name_ptr
= NULL
; /* force these values to null */
915 /* make sure there are no spaces in between equals */
916 equal_ptr
= strchr(string
, '=');
917 if (equal_ptr
== NULL
) {
922 /*! \todo Technically this isn't a correct if statement. This if will
923 * cause an invalid read for strings: =name and value=
925 if ( (*(equal_ptr
+ 1) == ' ') || (*(equal_ptr
- 1) == ' ') ) {
926 /* sometimes you have text with an ='s in it, it shouldn't be */
927 /* treated like an attribute */
930 s_log_message("Found attrib/text with spaces beside the ='s [%s]\n",
932 s_log_message("You can ignore the above message if the text is not intended to be an attribute\n");
933 fprintf(stderr
, "Found an attribute with spaces beside the ='s [%s]\n",
940 str_array
= g_strsplit (string
, "=", 2);
942 *name_ptr
= g_strdup(str_array
[0]);
943 *value_ptr
= g_strdup(str_array
[1]);
944 g_strfreev(str_array
);
946 if (*value_ptr
&& (*value_ptr
)[0] == '\0') {
947 s_log_message("Found an improper attribute: _%s_\n", string
);
948 #if 0 /* for now leak this memory till this is verified correct everywhere */
949 g_free(*name_ptr
); *name_ptr
= NULL
;
950 g_free(*value_ptr
); *value_ptr
= NULL
;
958 /*! \brief Free the currently selected attribute.
959 * \par Function Description
960 * Free the currently selected attribute.
962 * \param [in] w_current The TOPLEVEL object containing current attribute.
965 void o_attrib_free_current(TOPLEVEL
*w_current
)
967 if (w_current
->current_attribute
) {
968 g_free(w_current
->current_attribute
);
970 w_current
->current_attribute
=NULL
;
973 /*! \brief Set current show flag.
974 * \par Function Description
975 * Set current show flag.
977 * \param [in] w_current The TOPLEVEL object.
978 * \param [in] flag Any value which show_name_value takes.
983 void o_attrib_set_show(TOPLEVEL
*w_current
, int flag
)
985 w_current
->current_show
= flag
;
988 /*! \brief Set current visibility flag.
989 * \par Function Description
990 * Set current visibility flag.
992 * \param [in] w_current The TOPLEVEL object.
993 * \param [in] flag Allowed values are:
998 o_attrib_set_visible(TOPLEVEL
*w_current
, int flag
)
1000 w_current
->current_visible
= flag
;
1003 /*! \brief Set an attribute's string.
1004 * \par Function Description
1005 * Set an attribute's string.
1007 * \param [in] w_current The TOPLEVEL object that holds the attribute.
1008 * \param [in] string The value to set attribute string to.
1011 * The user of this function must g_free the
1012 * <B>w_current->current_attribute</B> string after done using it.
1013 * They must also free the input string.
1015 void o_attrib_set_string(TOPLEVEL
*w_current
, char *string
)
1019 /* need to put an error messages here */
1020 if (string
== NULL
) {
1021 fprintf(stderr
, "error! string in set_string was NULL\n");
1025 if (w_current
->current_attribute
!= NULL
) {
1026 g_free(w_current
->current_attribute
);
1027 w_current
->current_attribute
=NULL
;
1030 len
= strlen(string
);
1032 w_current
->current_attribute
= (char *) g_malloc(sizeof(char)*len
+1);
1034 strcpy(w_current
->current_attribute
,string
);
1036 /* be sure to g_free this string somewhere and free the input string */
1039 /*! \brief Get the parent OBJECT of an attribute.
1040 * \par Function Description
1041 * Get the parent OBJECT of an attribute.
1043 * \param [in] attribute ATTRIB pointer to get parent of.
1044 * \return The parent OBJECT if it exists, otherwise NULL.
1046 OBJECT
*o_attrib_return_parent(ATTRIB
*attribute
)
1050 a_current
= attribute
;
1056 while (a_current
->prev
!= NULL
) {
1057 a_current
= a_current
->prev
;
1060 /* should be pointing to the parent */
1062 return(a_current
->object
);
1065 /*! \brief Copy all attributes.
1066 * \par Function Description
1067 * This function will copy all attributes from the provided list
1068 * by attaching them to the provided OBJECT list.
1070 * \param [in] w_current The TOPLEVEL object.
1071 * \param [out] attached_to OBJECT list to copy attributes to.
1072 * \param [in] attributes ATTRIB list to copy attributes from.
1073 * \return new attribute list.
1075 ATTRIB
*o_attrib_copy_all(TOPLEVEL
*w_current
, OBJECT
*attached_to
,
1078 ATTRIB
*a_current
=NULL
;
1079 ATTRIB
*a_head
=NULL
;
1081 ATTRIB
*a_prev
=NULL
;
1083 a_current
= attributes
;
1085 while (a_current
!= NULL
) {
1087 a_new
= (ATTRIB
*) g_malloc(sizeof(ATTRIB
));
1089 /* in the case of the head attrib node, object points to
1090 * the parent which the attributes are attached to */
1091 if (a_head
== NULL
) {
1092 a_new
->object
= attached_to
;
1094 a_new
->object
= a_current
->object
;
1099 /* object is not null and a_start is not null (ie we are not
1100 * messing with the head attrib node)
1102 if (a_new
->object
&& a_head
!= NULL
) {
1103 a_new
->object
->attached_to
= a_new
;
1106 a_new
->copied_to
= a_current
->copied_to
;
1108 a_new
->prev
= a_prev
;
1110 /* set previous's next pointer */
1111 /* if it's null that means we are at the first attrib */
1113 a_prev
->next
= a_new
;
1120 a_current
= a_current
->next
;
1123 /* should be pointing to the head node */
1127 /*! \brief Reattach attributes.
1128 * \par Function Description
1129 * Reattach attributes.
1131 * \param [in] attributes ATTRIB list to reattach.
1133 void o_attrib_reattach(ATTRIB
*attributes
)
1135 ATTRIB
*a_current
=NULL
;
1137 a_current
= attributes
;
1139 /* skip over head node */
1141 a_current
= a_current
->next
;
1143 while (a_current
!= NULL
) {
1144 if (a_current
->object
) {
1145 a_current
->object
->attached_to
= a_current
;
1146 a_current
->object
->attribute
= 1;
1148 a_current
= a_current
->next
;
1152 /*! \brief Set attribute color
1153 * \par Function Description
1154 * This function sets all attribute objects to the right
1155 * color (attribute_color).
1157 * \param [in] w_current The TOPLEVEL object.
1158 * \param [in,out] attributes ATTRIB list to set colors on.
1161 void o_attrib_set_color(TOPLEVEL
*w_current
, ATTRIB
*attributes
)
1165 a_current
= attributes
;
1167 /* skip over head */
1169 a_current
= a_current
->next
;
1171 while (a_current
!= NULL
) {
1173 if (a_current
->object
) {
1175 if (a_current
->object
->type
== OBJ_TEXT
&&
1176 a_current
->object
->text
->prim_objs
) {
1178 /* I'm not terribly happy with this */
1180 if (a_current
->object
->saved_color
!= -1) {
1182 /* if the object is selected, make */
1183 /* sure it it say selected */
1184 o_complex_set_color(
1185 a_current
->object
->text
->prim_objs
,
1187 a_current
->object
->color
=
1190 o_complex_set_saved_color_only(
1191 a_current
->object
->text
->prim_objs
,
1192 w_current
->attribute_color
);
1193 a_current
->object
->saved_color
= w_current
->
1197 o_complex_set_color(
1198 a_current
->object
->text
->prim_objs
,
1199 w_current
->attribute_color
);
1200 a_current
->object
->color
=
1201 w_current
->attribute_color
;
1205 a_current
= a_current
->next
;
1210 /*! \brief Search for attibute by name.
1211 * \par Function Description
1212 * Search for attribute by name.
1215 * The list is the top level list. Do not pass it an object_head list
1216 * unless you know what you are doing.
1218 * Counter is the n'th occurance of the attribute, and starts searching
1219 * from zero. Zero is the first occurance of an attribute.
1221 * \param [in] list OBJECT list to search.
1222 * \param [in] name Character string with attribute name to search for.
1223 * \param [in] counter Which occurance to return.
1224 * \return Character string with attribute value, NULL otherwise.
1227 * Caller must g_free returned character string.
1229 char *o_attrib_search_name(OBJECT
*list
, char *name
, int counter
)
1235 int internal_counter
=0;
1236 char *found_name
= NULL
;
1237 char *found_value
= NULL
;
1238 char *return_string
= NULL
;
1242 while(o_current
!= NULL
) {
1243 if (o_current
->attribs
!= NULL
) {
1244 a_current
= o_current
->attribs
;
1246 while(a_current
!= NULL
) {
1247 found
= a_current
->object
;
1248 if (found
!= NULL
) {
1249 if (found
->type
== OBJ_TEXT
) {
1250 val
= o_attrib_get_name_value(found
->text
->string
,
1251 &found_name
, &found_value
);
1254 if (strcmp(name
, found_name
) == 0) {
1255 if (counter
!= internal_counter
) {
1258 return_string
= (char *)
1259 g_malloc(sizeof(char)*strlen(found_value
)+1);
1260 strcpy(return_string
, found_value
);
1261 if (found_name
) g_free(found_name
);
1262 if (found_value
) g_free(found_value
);
1263 return(return_string
);
1266 if (found_name
) { g_free(found_name
); found_name
= NULL
; }
1267 if (found_value
) { g_free(found_value
); found_value
= NULL
; }
1271 printf("0 _%s_\n", found
->text
->string
);
1272 printf("1 _%s_\n", found_name
);
1273 printf("2 _%s_\n", found_value
);
1277 a_current
=a_current
->next
;
1281 /* search for attributes outside */
1283 if (o_current
->type
== OBJ_TEXT
) {
1284 if (found_name
) g_free(found_name
);
1285 if (found_value
) g_free(found_value
);
1286 val
= o_attrib_get_name_value(o_current
->text
->string
,
1287 &found_name
, &found_value
);
1289 if (strcmp(name
, found_name
) == 0) {
1290 if (counter
!= internal_counter
) {
1293 return_string
= (char *)
1294 g_malloc(sizeof(char)* strlen(found_value
)+1);
1295 strcpy(return_string
, found_value
);
1296 if (found_name
) g_free(found_name
);
1297 if (found_value
) g_free(found_value
);
1298 return(return_string
);
1301 if (found_name
) { g_free(found_name
); found_name
= NULL
; }
1302 if (found_value
) { g_free(found_value
); found_value
= NULL
; }
1306 o_current
=o_current
->next
;
1309 if (found_name
) g_free(found_name
);
1310 if (found_value
) g_free(found_value
);
1314 /*! \brief Search OBJECT list for text string.
1315 * \par Function Description
1316 * Given an OBJECT list (i.e. OBJECTs on schematic page or
1317 * inside symbol), search for the attribute called out in
1318 * "string". It iterates over all objects in the OBJECT list
1319 * and dives into the attached ATTRIB list for
1320 * each OBJECT if it finds one.
1321 * Inside the ATTRIB list it looks for an attached text
1322 * attribute matching "string". It returns the
1323 * pointer to the associated OBJECT if found. If the attribute
1324 * string is not found in the ATTRIB list, then the fcn
1325 * looks on the OBJECT itself for the attribute. Then it
1326 * iterates to the next OBJECT.
1329 * The list is the top level list. Do not pass it an object_head list
1330 * unless you know what you are doing.
1332 * \param [in] list OBJECT list to search.
1333 * \param [in] string Character string to search for.
1334 * \return A matching OBJECT if found, NULL otherwise.
1336 OBJECT
*o_attrib_search_string_list(OBJECT
*list
, char *string
)
1344 while(o_current
!= NULL
) {
1345 /* first search attribute list */
1346 if (o_current
->attribs
!= NULL
) {
1347 a_current
= o_current
->attribs
;
1349 while(a_current
!= NULL
) {
1350 found
= a_current
->object
;
1351 if (found
!= NULL
) {
1352 if (found
->type
== OBJ_TEXT
) {
1354 printf("libgeda:o_attrib.c:o_attrib_search_string_list --");
1355 printf("found OBJ_TEXT, string = %s\n", found
->text
->string
);
1357 if (strcmp(string
, found
->text
->string
) == 0) {
1362 a_current
=a_current
->next
;
1366 /* search for attributes outside (ie the actual object) */
1367 if (o_current
->type
== OBJ_TEXT
) {
1368 if (strcmp(string
, o_current
->text
->string
) == 0) {
1373 o_current
=o_current
->next
;
1379 /*! \brief Search list for partial string match.
1380 * \par Function Description
1381 * Search list for partial string match.
1383 * Counter is the n'th occurance of the attribute, and starts searching
1384 * from zero. Zero is the first occurance of an attribute.
1386 * \param [in] object The OBJECT list to search.
1387 * \param [in] search_for Partial character string to search for.
1388 * \param [in] counter Which occurance to return.
1389 * \return Matching object value if found, NULL otherwise.
1392 * Caller must g_free returned character string.
1394 char *o_attrib_search_string_partial(OBJECT
*object
, char *search_for
,
1399 int internal_counter
=0;
1400 char *found_name
= NULL
;
1401 char *found_value
= NULL
;
1402 char *return_string
= NULL
;
1406 if (o_current
== NULL
) {
1410 if (o_current
->type
== OBJ_TEXT
) {
1411 if (strstr(o_current
->text
->string
, search_for
)) {
1412 if (counter
!= internal_counter
) {
1415 val
= o_attrib_get_name_value(o_current
->text
->string
,
1416 &found_name
, &found_value
);
1418 return_string
= g_strdup(found_value
);
1419 if (found_name
) g_free(found_name
);
1420 if (found_value
) g_free(found_value
);
1421 return(return_string
);
1427 if (found_name
) g_free(found_name
);
1428 if (found_value
) g_free(found_value
);
1432 /*! \brief Check if object matches string.
1433 * \par Function Description
1434 * This function will check if the text->string value of
1435 * the passed OBJECT matches the <B>search_for</B> parameter.
1436 * If not, it then searches the object's ATTRIB list (if
1438 * Only this single OBJECT and its ATTRIB list is
1439 * checked, and other OBJECTs on the page are not checked.
1440 * \param [in] object The OBJECT to compare.
1441 * \param [in] search_for Character string to compare against.
1442 * Usually name=value
1443 * \return The OBJECT passed in <B>object</B> parameter, NULL otherwise.
1445 OBJECT
*o_attrib_search_string_single(OBJECT
*object
, char *search_for
)
1454 printf("In libgeda:o_attrib.c:o_attrib_search_string_single\n");
1455 printf(" Examining object->name = %s\n", object
->name
);
1458 if (o_current
== NULL
) {
1462 /* First check to see if this OBJECT itself is the attribute we want */
1463 if (o_current
->type
== OBJ_TEXT
) {
1464 if (strcmp(o_current
->text
->string
, search_for
) == 0) {
1466 printf(" This object is searched-for attribute\n");
1472 /* Next check to see if this OBJECT has an ATTRIB list we */
1473 /* can search. If not return NULL. If so, search it. */
1474 if (o_current
->attribs
== NULL
)
1477 a_current
= o_current
->attribs
;
1478 while(a_current
!= NULL
) {
1479 found
= a_current
->object
;
1480 if (found
!= NULL
) {
1481 if (found
->type
== OBJ_TEXT
) {
1482 if(strcmp(found
->text
->string
, search_for
) == 0) {
1487 a_current
=a_current
->next
;
1493 /*! \brief Search for attribute by value and name.
1494 * \par Function Description
1495 * Search for attribute by value and name.
1497 * Counter is the n'th occurance of the attribute, and starts searching
1498 * from zero. Zero is the first occurance of an attribute.
1500 * The value is the primary search key, but name is checked before
1501 * an OBJECT is returned to ensure the correct OBJECT has been found.
1503 * \param [in] list The ATTRIB list to search.
1504 * \param [in] value Character string with value to search for.
1505 * \param [in] name Character string with name to compare.
1506 * \param [in] counter Which occurance to return.
1507 * \return The attribute OBJECT if found, NULL otherwise.
1510 OBJECT
*o_attrib_search_attrib_value(ATTRIB
*list
, char *value
, char *name
,
1516 int internal_counter
=0;
1517 char *found_name
= NULL
;
1518 char *found_value
= NULL
;
1528 while(a_current
!= NULL
) {
1529 found
= a_current
->object
;
1530 if (found
!= NULL
) {
1531 if (found
->type
== OBJ_TEXT
) {
1532 val
= o_attrib_get_name_value(found
->text
->string
,
1533 &found_name
, &found_value
);
1537 printf("found value: %s\n", found_value
);
1538 printf("looking for: %s\n", value
);
1540 if (strcmp(value
, found_value
) == 0) {
1541 if (counter
!= internal_counter
) {
1544 if (strstr(found_name
, name
)) {
1545 if (found_name
) g_free(found_name
);
1546 if (found_value
) g_free(found_value
);
1551 if (found_name
) { g_free(found_name
); found_name
= NULL
; }
1552 if (found_value
) { g_free(found_value
); found_value
= NULL
; }
1557 a_current
=a_current
->next
;
1560 if (found_name
) g_free(found_name
);
1561 if (found_value
) g_free(found_value
);
1565 /*! \brief Search for an attribute by name.
1566 * \par Function Description
1567 * Search for an attribute by name.
1569 * Counter is the n'th occurance of the attribute, and starts searching
1570 * from zero. Zero is the first occurance of an attribute.
1572 * \param [in] list ATTRIB list to search.
1573 * \param [in] name Character string with attribute name to search for.
1574 * \param [in] counter Which occurance to return.
1575 * \return Character string with attribute value, NULL otherwise.
1578 * Caller must g_free returned character string.
1581 o_attrib_search_attrib_name(ATTRIB
*list
, char *name
, int counter
)
1586 int internal_counter
=0;
1587 char *found_name
= NULL
;
1588 char *found_value
= NULL
;
1589 char *return_string
= NULL
;
1593 while(a_current
!= NULL
) {
1594 found
= a_current
->object
;
1595 if (found
!= NULL
) {
1596 if (found
->type
== OBJ_TEXT
) {
1597 val
= o_attrib_get_name_value(found
->text
->string
,
1598 &found_name
, &found_value
);
1602 printf("found name: %s\n", found_name
);
1603 printf("looking for: %s\n", name
);
1605 if (strcmp(name
, found_name
) == 0) {
1606 if (counter
!= internal_counter
) {
1609 return_string
= (char *)
1610 g_malloc(sizeof(char)* strlen(found_value
)+1);
1611 strcpy(return_string
, found_value
);
1612 if (found_name
) g_free(found_name
);
1613 if (found_value
) g_free(found_value
);
1614 return(return_string
);
1617 if (found_name
) { g_free(found_name
); found_name
= NULL
; }
1618 if (found_value
) { g_free(found_value
); found_value
= NULL
; }
1622 a_current
=a_current
->next
;
1625 if (found_name
) g_free(found_name
);
1626 if (found_value
) g_free(found_value
);
1630 /*! \brief Search TOPLEVEL attributes.
1631 * \par Function Description
1632 * This function should only be used to search for TOPLEVEL attributes.
1634 * The list is the top level list. Do not pass it an object_head list
1635 * unless you know what you are doing.
1637 * Counter is the n'th occurance of the attribute, and starts searching
1638 * from zero. Zero is the first occurance of an attribute.
1640 * \param [in] list The OBJECT list to search (TOPLEVEL only).
1641 * \param [in] name Character string of attribute name to search for.
1642 * \param [in] counter Which occurance to return.
1643 * \return Character string with attribute value, NULL otherwise.
1646 * Caller must g_free returned character string.
1648 char *o_attrib_search_toplevel(OBJECT
*list
, char *name
, int counter
)
1652 int internal_counter
=0;
1653 char *found_name
= NULL
;
1654 char *found_value
= NULL
;
1655 char *return_string
= NULL
;
1659 while(o_current
!= NULL
) {
1661 /* search for attributes outside */
1663 if (o_current
->type
== OBJ_TEXT
) {
1664 val
= o_attrib_get_name_value(o_current
->text
->string
,
1665 &found_name
, &found_value
);
1667 if (strcmp(name
, found_name
) == 0) {
1668 if (counter
!= internal_counter
) {
1671 return_string
= (char *)
1672 g_malloc(sizeof(char)* strlen(found_value
)+1);
1673 strcpy(return_string
, found_value
);
1674 if (found_name
) g_free(found_name
);
1675 if (found_value
) g_free(found_value
);
1676 return(return_string
);
1679 if (found_name
) { g_free(found_name
); found_name
= NULL
; }
1680 if (found_value
) { g_free(found_value
); found_value
= NULL
; }
1684 o_current
=o_current
->next
;
1687 if (found_name
) g_free(found_name
);
1688 if (found_value
) g_free(found_value
);
1692 /*! \brief Search for special attributes.
1693 * \par Function Description
1694 * This function will search an OBJECT list for the special
1695 * attributes <EM>"gnd"</EM> and <EM>"vdd"</EM>.
1697 * \param [in] o_current The OBJECT list to search.
1698 * \return Character string with attribute value, NULL otherwise.
1701 * Caller must g_free returned character string.
1703 /* be sure caller free's return value */
1704 char *o_attrib_search_special(OBJECT
*o_current
)
1708 return_value
= o_attrib_search_name(o_current
->complex->prim_objs
,
1712 return(return_value
);
1715 return_value
= o_attrib_search_name(o_current
->complex->prim_objs
,
1719 return(return_value
);
1725 /*! \brief Search for first occurance of a named attribute.
1726 * \par Function Description
1727 * Search for first occurance of a named attribute.
1729 * \param [in] object The OBJECT list to search.
1730 * \param [in] name Character string of attribute name to search for.
1731 * \param [out] return_found Contains attribute OBJECT if found, NULL otherwise.
1732 * \return Character string with attribute value, NULL otherwise.
1735 * Caller must g_free returned character string.
1737 char *o_attrib_search_name_single(OBJECT
*object
, char *name
,
1738 OBJECT
**return_found
)
1744 char *found_name
= NULL
;
1745 char *found_value
= NULL
;
1746 char *return_string
= NULL
;
1750 if (o_current
== NULL
) {
1754 if (o_current
->attribs
!= NULL
) {
1755 a_current
= o_current
->attribs
;
1757 while(a_current
!= NULL
) {
1758 found
= a_current
->object
;
1759 if (found
!= NULL
) {
1760 if (found
->type
== OBJ_TEXT
) {
1761 val
= o_attrib_get_name_value(found
->text
->string
,
1762 &found_name
, &found_value
);
1765 if (strcmp(name
, found_name
) == 0) {
1766 return_string
= (char *)
1767 g_malloc(sizeof(char)* strlen(found_value
)+1);
1768 strcpy(return_string
, found_value
);
1770 *return_found
= found
;
1772 if (found_name
) g_free(found_name
);
1773 if (found_value
) g_free(found_value
);
1774 return(return_string
);
1776 if (found_name
) { g_free(found_name
); found_name
= NULL
; }
1777 if (found_value
) { g_free(found_value
); found_value
= NULL
; }
1781 printf("0 _%s_\n", found
->text
->string
);
1782 printf("1 _%s_\n", found_name
);
1783 printf("2 _%s_\n", found_value
);
1787 a_current
=a_current
->next
;
1790 /* search for attributes outside */
1792 if (o_current
->type
== OBJ_TEXT
) {
1793 if (found_name
) g_free(found_name
);
1794 if (found_value
) g_free(found_value
);
1795 val
= o_attrib_get_name_value(o_current
->text
->string
,
1796 &found_name
, &found_value
);
1799 if (strcmp(name
, found_name
) == 0) {
1800 return_string
= (char *)
1801 g_malloc(sizeof(char)* strlen(found_value
)+1);
1802 strcpy(return_string
, found_value
);
1804 *return_found
= found
;
1806 if (found_name
) g_free(found_name
);
1807 if (found_value
) g_free(found_value
);
1808 return(return_string
);
1810 if (found_name
) { g_free(found_name
); found_name
= NULL
; }
1811 if (found_value
) { g_free(found_value
); found_value
= NULL
; }
1816 *return_found
= NULL
;
1819 if (found_name
) g_free(found_name
);
1820 if (found_value
) g_free(found_value
);
1824 /*! \brief Search for N'th occurance of a named attribute.
1825 * \par Function Description
1826 * Search for N'th occurance of a named attribute.
1828 * \param [in] object The OBJECT list to search.
1829 * \param [in] name Character string of attribute name to search for.
1830 * \param [in] counter Which occurance to return.
1831 * \return Character string with attribute value, NULL otherwise.
1834 * Caller must g_free returned character string.
1836 /* be sure caller free's return value */
1837 /* this function is like above, except that it returns the n'th occurance */
1838 /* of the attribute. counter starts counting at zero */
1839 char *o_attrib_search_name_single_count(OBJECT
*object
, char *name
,
1846 char *found_name
= NULL
;
1847 char *found_value
= NULL
;
1848 char *return_string
= NULL
;
1849 int internal_counter
=0;
1854 if (o_current
== NULL
) {
1858 if (o_current
->attribs
!= NULL
) {
1859 a_current
= o_current
->attribs
;
1861 while(a_current
!= NULL
) {
1862 found
= a_current
->object
;
1863 if (found
!= NULL
) {
1864 if (found
->type
== OBJ_TEXT
) {
1865 val
= o_attrib_get_name_value(found
->text
->string
,
1866 &found_name
, &found_value
);
1869 if (strcmp(name
, found_name
) == 0) {
1870 if (counter
!= internal_counter
) {
1873 return_string
= (char *)
1874 g_malloc(sizeof(char)* strlen(found_value
)+1);
1875 strcpy(return_string
, found_value
);
1876 if (found_name
) g_free(found_name
);
1877 if (found_value
) g_free(found_value
);
1878 return(return_string
);
1881 if (found_name
) { g_free(found_name
); found_name
= NULL
; }
1882 if (found_value
) { g_free(found_value
); found_value
= NULL
; }
1886 printf("0 _%s_\n", found
->text
->string
);
1887 printf("1 _%s_\n", found_name
);
1888 printf("2 _%s_\n", found_value
);
1892 a_current
=a_current
->next
;
1896 /* search for attributes outside */
1898 if (o_current
->type
== OBJ_TEXT
) {
1899 if (found_name
) g_free(found_name
);
1900 if (found_value
) g_free(found_value
);
1901 val
= o_attrib_get_name_value(o_current
->text
->string
,
1902 &found_name
, &found_value
);
1905 if (strcmp(name
, found_name
) == 0) {
1906 if (counter
!= internal_counter
) {
1909 return_string
= (char *)
1910 g_malloc(sizeof(char)* strlen(found_value
)+1);
1911 strcpy(return_string
, found_value
);
1912 if (found_name
) g_free(found_name
);
1913 if (found_value
) g_free(found_value
);
1914 return(return_string
);
1917 if (found_name
) { g_free(found_name
); found_name
= NULL
; }
1918 if (found_value
) { g_free(found_value
); found_value
= NULL
; }
1922 if (found_name
) g_free(found_name
);
1923 if (found_value
) g_free(found_value
);
1927 /*! \brief Search for slot attribute.
1928 * \par Function Description
1929 * Search for slot attribute.
1931 * \param [in] object OBJECT list to search.
1932 * \param [in] return_found slot attribute if found, NULL otherwise.
1933 * \return Character string with attribute value, NULL otherwise.
1936 * Caller must g_free returned character string
1938 char *o_attrib_search_slot(OBJECT
*object
, OBJECT
**return_found
)
1942 /* search for default value attribute buried inside the complex */
1943 return_value
= o_attrib_search_name_single(object
, "slot", return_found
);
1945 /* I'm confused here does the next if get ever called? */
1947 return(return_value
);
1951 *return_found
= NULL
;
1956 /*! \brief Search for numslots attribute.
1957 * \par Function Description
1958 * Search for numslots attribute.
1960 * \param [in] object OBJECT to search.
1961 * \param [in] return_found numslots attribute if found, NULL otherwise.
1962 * \return Character string with attribute value, NULL otherwise.
1965 * Caller must g_free returned character string.
1967 char *o_attrib_search_numslots(OBJECT
*object
, OBJECT
**return_found
)
1969 char *return_value
= NULL
;
1971 /* search for numslots attribute buried inside the complex */
1972 if (object
->type
== OBJ_COMPLEX
) {
1973 return_value
= o_attrib_search_name(object
->complex->prim_objs
,
1978 return(return_value
);
1982 *return_found
= NULL
;
1987 /*! \brief Search for default slot attribute.
1988 * \par Function Description
1989 * Search for default slot attribute.
1991 * \param [in] object OBJECT list to search.
1992 * \return Character string with attribute value, NULL otherwise.
1995 * Caller must g_free returned character string.
1997 char *o_attrib_search_default_slot(OBJECT
*object
)
2001 /* search for default value attribute buried inside the complex */
2002 return_value
= o_attrib_search_name(object
->complex->prim_objs
,
2006 return(return_value
);
2012 /*! \brief Search pinseq attribute.
2013 * \par Function Description
2014 * Given list of objects (generally a pin with attached attribs),
2016 * search for and return pinseq= attrib (object).
2018 * \param [in] list OBJECT list to search.
2019 * \param [in] pin_number pin number to search for.
2020 * \return OBJECT containing pinseq data, NULL otherwise.
2022 OBJECT
*o_attrib_search_pinseq(OBJECT
*list
, int pin_number
)
2024 OBJECT
*pinseq_text_object
;
2027 /* The 9 is the number of allowed digits plus null */
2028 search_for
= (char *) g_malloc(sizeof(char)*(strlen("pinseq=")+9));
2029 sprintf(search_for
, "pinseq=%d", pin_number
);
2031 pinseq_text_object
= o_attrib_search_string_list(list
, search_for
);
2034 if (pinseq_text_object
&& pinseq_text_object
->attached_to
) {
2035 return(o_attrib_return_parent(pinseq_text_object
->attached_to
));
2041 /*! \brief Search for slotdef attribute.
2042 * \par Function Description
2043 * Search for slotdef attribute.
2045 * \param [in] object The OBJECT list to search.
2046 * \param [in] slotnumber The slot number to search for.
2047 * \return Character string with attribute value, NULL otherwise.
2050 * Caller must g_free returned character string.
2052 char *o_attrib_search_slotdef(OBJECT
*object
, int slotnumber
)
2054 char *return_value
=NULL
;
2055 char *search_for
=NULL
;
2058 /* The 9 is the number of digits plus null */
2059 search_for
= (char *) g_malloc(sizeof(char)*(strlen("slotdef=:")+9));
2061 sprintf(search_for
, "slotdef=%d:", slotnumber
);
2063 o_current
= object
->complex->prim_objs
;
2064 while (o_current
!= NULL
) {
2065 return_value
= o_attrib_search_string_partial(o_current
, search_for
, 0);
2069 o_current
= o_current
->next
;
2074 return(return_value
);
2080 /*! \brief Search for component.
2081 * \par Function Description
2082 * Search for component.
2084 * \param [in] object The OBJECT list to search.
2085 * \param [in] name Character string containing component name to match.
2086 * \return Character string with the component value, NULL otherwise.
2088 char *o_attrib_search_component(OBJECT
*object
, char *name
)
2090 char *return_value
= NULL
;
2096 if (object
->type
!= OBJ_COMPLEX
&& object
->type
!= OBJ_PLACEHOLDER
) {
2100 /* first look inside the complex object */
2101 return_value
= o_attrib_search_name(object
->complex->prim_objs
,
2105 return(return_value
);
2108 /* now look outside to see if it was attached externally */
2109 return_value
= o_attrib_search_name_single(object
, name
, NULL
);
2112 return(return_value
);
2118 /*! \brief Update all slot attributes in an object.
2119 * \par Function Description
2120 * Update pinnumber attributes in a graphic object.
2121 * The interesting case is where the object is an
2122 * instantiation of a slotted part. This means that
2123 * o_attrib_slot_update iterates through all pins
2124 * found on object and sets the pinnumber= attrib
2125 * on each. This doesn't matter for non-slotted
2126 * parts, but on slotted parts, this is what sets the
2127 * pinnumber= attribute on slots 2, 3, 4....
2129 * \param [in] w_current The TOPLEVEL object.
2130 * \param [in,out] object The OBJECT to update.
2132 void o_attrib_slot_update(TOPLEVEL
*w_current
, OBJECT
*object
)
2134 OBJECT
*o_current
; /* o_current points to the sch level complex object */
2135 OBJECT
*o_slot_attrib
;
2136 OBJECT
*o_pin_object
;
2137 OBJECT
*o_pinnum_object
;
2138 OBJECT
*o_pinseq_object
;
2142 int pin_counter
; /* Internal pin counter private to this fcn. */
2143 char *new_pinseq
; /* New pinseq = (slot*(number of pins -1) + pin_count */
2144 int numpins
; /* Total number of pins on this slot */
2145 char* current_pin
; /* text from slotdef= to be made into pinnumber= */
2146 char* cptr
; /* char pointer pointing to pinnumbers in slotdef=#:#,#,# string */
2149 /* For this particular graphic object (component instantiation) */
2150 /* get the slot number as a string */
2151 string
= o_attrib_search_slot(o_current
, &o_slot_attrib
);
2154 /* s_log_message("Did not find slot= attribute\n"); */
2155 /* not a serious error */
2158 slot
= atoi(string
);
2161 /* OK, now that we have the slot number, use it to get the */
2162 /* corresponding slotdef=#:#,#,# string. */
2163 slotdef
= o_attrib_search_slotdef(o_current
, slot
);
2166 s_log_message("Did not find slotdef=#:#,#,#... attribute\n");
2170 if (!strstr(slotdef
, ":")) {
2171 /* Didn't find proper slotdef=#:... put warning into log */
2172 s_log_message("Improper slotdef syntax: missing \":\".\n");
2177 /* skip over slotdef number */
2178 /* slotdef is in the form #:#,#,# */
2179 /* this code skips first #: */
2181 while (*cptr
!= '\0' && *cptr
!= ':') {
2184 cptr
++; /* skip colon */
2186 if (*cptr
== '\0') {
2187 s_log_message("Did not find proper slotdef=#:#,#,#... attribute\n");
2192 /* loop on all pins found in slotdef= attribute */
2193 pin_counter
= 1; /* internal pin_counter */
2194 /* get current pinnumber= from slotdef= attrib */
2195 current_pin
= strtok(cptr
, DELIMITERS
);
2196 while(current_pin
!= NULL
) {
2197 /* get pin on this component with pinseq == pin_counter */
2198 o_pin_object
= o_attrib_search_pinseq(o_current
->complex->prim_objs
,
2202 /* Now rename pinnumber= attrib on this part with value found */
2203 /* in slotdef attribute */
2204 string
= o_attrib_search_name_single(o_pin_object
, "pinnumber",
2207 if (string
&& o_pinnum_object
&& o_pinnum_object
->type
== OBJ_TEXT
&&
2208 o_pinnum_object
->text
->string
) {
2209 g_free(o_pinnum_object
->text
->string
);
2211 /* 9 is the size of one number plus null character */
2212 o_pinnum_object
->text
->string
= (char *)
2213 g_malloc(sizeof(char)*(strlen("pinnumber=")+strlen(current_pin
)+9));
2215 /* removed _int from current_pin */
2216 sprintf(o_pinnum_object
->text
->string
, "pinnumber=%s", current_pin
);
2218 o_text_recreate(w_current
, o_pinnum_object
);
2225 /* Now update pinseq= attrib on this part. */
2227 * 1. Get pointer to pinseq= attrib (graphic object) on this part.
2228 * 2. Verify it has a pinseq= string attached.
2229 * 3. free pinseq string.
2230 * 4. figure out how many pins are on this part.
2231 * 5. Write new string pinseq=(slot * (number of pins-1)) + pin_counter
2232 * into pinseq= object.
2234 string
= o_attrib_search_name_single(o_pin_object
, "pinseq",
2237 if (string
&& o_pinseq_object
&& o_pinseq_object
->type
== OBJ_TEXT
&&
2238 o_pinseq_object
->text
->string
) {
2239 g_free(o_pinseq_object
->text
->string
); /* free old pinseq text */
2241 /* I need to check that the return is non-zero! */
2242 numpins
= o_complex_count_pins(o_current
);
2245 printf("libgeda:o_attrib.c:o_attrib_slot_update -- name = %s\n", o_current
->name
);
2246 printf(" numpins = %d\n", numpins
);
2249 /* Now put new pinseq attrib onto pin. */
2250 new_pinseq
= g_malloc(sizeof(char)*((numpins
-1)*slot
)+pin_counter
);
2251 sprintf(new_pinseq
, "%d", numpins
*(slot
-1)+pin_counter
);
2252 /* Add 1 for EOL char */
2253 o_pinseq_object
->text
->string
= (char *)
2254 g_malloc(sizeof(char)*(strlen("pinseq=") +
2255 strlen(new_pinseq
) +1 ));
2257 sprintf(o_pinseq_object
->text
->string
, "pinseq=%s", new_pinseq
);
2260 printf("libgeda:o_attrib.c:o_attrib_slot_update -- ");
2261 printf("new_pinseq attrib = %s \n", o_pinseq_object
->text
->string
);
2264 o_text_recreate(w_current
, o_pinseq_object
);
2272 s_log_message("component missing pinseq= attribute\n");
2275 current_pin
= strtok(NULL
, DELIMITERS
);
2281 /*! \brief Copy attributes from OBJECT to OBJECT.
2282 * \par Function Description
2283 * This function will perform a slot copy of the <B>original</B> OBJECT
2284 * to the <B>target</B> OBJECT.
2286 * \param [in] w_current The TOPLEVEL object.
2287 * \param [in] original The original OBJECT to slot copy from.
2288 * \param [out] target The target OBJECT to slot copy to.
2290 void o_attrib_slot_copy(TOPLEVEL
*w_current
, OBJECT
*original
, OBJECT
*target
)
2294 OBJECT
*o_slot_attrib
;
2295 OBJECT
*o_pin_object
;
2296 OBJECT
*o_pinnum_object
;
2304 o_current
= original
;
2306 string
= o_attrib_search_slot(o_current
, &o_slot_attrib
);
2309 /* s_log_message("Did not find slot= attribute\n"); */
2310 /* not a serious error */
2313 slot
= atoi(string
);
2316 slotdef
= o_attrib_search_slotdef(o_current
, slot
);
2319 s_log_message("Did not find slotdef=#:#,#,#... attribute\n");
2323 if (!strstr(slotdef
, ":")) {
2324 /*! \todo didn't proper slotdef=#:... TODO into log*/
2328 /* skip over slotdef number */
2329 /* slotdef is in the form #:#,#,# */
2330 /* this code skips first #: */
2332 while (*cptr
!= '\0' && *cptr
!= ':') {
2335 cptr
++; /* skip colon */
2337 if (*cptr
== '\0') {
2338 s_log_message("Did not find proper slotdef=#:#,#,#... attribute\n");
2343 current_pin
= strtok(cptr
, DELIMITERS
);
2344 while(current_pin
!= NULL
) {
2346 o_pin_object
= o_attrib_search_pinseq(target
->complex->prim_objs
,
2351 string
= o_attrib_search_name_single(o_pin_object
, "pinnumber",
2354 if (string
&& o_pinnum_object
&& o_pinnum_object
->type
== OBJ_TEXT
&&
2355 o_pinnum_object
->text
->string
) {
2358 g_free(o_pinnum_object
->text
->string
);
2360 /* 9 is the size of one number plus null character */
2361 o_pinnum_object
->text
->string
= (char *)
2362 g_malloc(sizeof(char)*(strlen("pinnumber=")+strlen(current_pin
)+9));
2364 /* removed _int from current_pin */
2365 sprintf(o_pinnum_object
->text
->string
, "pinnumber=%s", current_pin
);
2367 o_text_recreate(w_current
, o_pinnum_object
);
2372 s_log_message("component missing pinseq= attribute\n");
2375 current_pin
= strtok(NULL
, DELIMITERS
);
2381 /*! \brief Get the number of TOPLEVEL attributes in all loaded pages.
2382 * \par Function Description
2383 * This function will return the number of TOPLEVEL attributes
2384 * in all loaded pages.
2386 * \param [in] w_current The TOPLEVEL object to search.
2387 * \param [in] name Attribute name to search for.
2388 * \return Count of TOPLEVEL attributes in all loaded pages.
2390 /* returns the number of toplevel attributes in all loaded pages */
2391 int o_attrib_count_toplevel(TOPLEVEL
*w_current
, char *name
)
2398 p_current
= w_current
->page_head
;
2400 while(p_current
!= NULL
) {
2403 string
= o_attrib_search_name(p_current
->object_head
,
2405 printf("%s %d\n", name
, counter
);
2413 string
= o_attrib_search_name(p_current
->object_head
,
2417 p_current
=p_current
->next
;
2422 /*! \brief Search for first TOPLEVEL attribute.
2423 * \par Function Description
2424 * This function searches all loaded pages for the first
2425 * TOPLEVEL attribute found.
2426 * The caller is responsible for freeing the returned value.
2427 * See #o_attrib_search_toplevel() for other comments.
2429 * \param [in] page_head PAGE head object to search through.
2430 * \param [in] name Character string name to search for.
2431 * \return Character string from the found attribute, NULL otherwise.
2433 char *o_attrib_search_toplevel_all(PAGE
*page_head
, char *name
)
2436 char *ret_value
=NULL
;
2438 p_current
= page_head
;
2440 while (p_current
!= NULL
) {
2443 /* don't look into the head of page_head */
2444 if (p_current
->pid
!= -1) {
2446 /* only look for first occurrance of the attribute */
2447 ret_value
= o_attrib_search_toplevel(
2448 p_current
->object_head
,
2452 if (ret_value
!= NULL
) {
2456 p_current
= p_current
->next
;
2462 /*! \brief Get all attached attributes to specified OBJECT.
2463 * \par Function Description
2464 * This function returns all attached attribute objects to the
2466 * The returned list is an array of objects and should be freed using the
2467 * #o_attrib_free_returned() function.
2468 * This function will only look for attached attributes and not
2469 * unattached free floating attribs.
2471 * \param [in] object_list OBJECT list to search.
2472 * \param [in] sel_object OBJECT to search for.
2473 * \return An array of objects that matched sel_object, NULL otherwise.
2475 OBJECT
** o_attrib_return_attribs(OBJECT
*object_list
, OBJECT
*sel_object
)
2477 OBJECT
**found_objects
;
2484 object
= (OBJECT
*) o_list_search(object_list
, sel_object
);
2490 if (!object
->attribs
) {
2494 if (!object
->attribs
->next
) {
2499 /* first go through and count the number of attribs */
2500 a_current
= object
->attribs
->next
;
2501 while(a_current
!= NULL
) {
2503 a_current
= a_current
->next
;
2506 found_objects
= (OBJECT
**) g_malloc(sizeof(OBJECT
*)*(num_attribs
+1));
2508 /* now actually fill the array of objects */
2509 a_current
= object
->attribs
->next
;
2510 while(a_current
!= NULL
) {
2511 if (a_current
->object
!= NULL
) {
2512 o_current
= a_current
->object
;
2513 if (o_current
->type
== OBJ_TEXT
&&
2514 o_current
->text
->string
) {
2515 found_objects
[i
] = o_current
;
2519 a_current
= a_current
->next
;
2522 found_objects
[i
] = NULL
;
2526 while(found_objects
[i
] != NULL
) {
2527 /*for (i = 0 ; i < num_attribs; i++) {*/
2528 printf("%d : %s\n", i
, found_objects
[i
]->text
->string
);
2533 return(found_objects
);
2536 /*! \brief Free attached attribute list.
2537 * \par Function Description
2538 * Free attached attribute list. Use only on a list created
2539 * by #o_attrib_return_attribs().
2541 * \param [in] found_objects List returned by #o_attrib_return_attribs().
2543 void o_attrib_free_returned(OBJECT
**found_objects
)
2547 if (!found_objects
) {
2551 /* don't free the insides of found_objects, since the contents are */
2552 /* just pointers into the real object list */
2553 while(found_objects
[i
] != NULL
) {
2554 found_objects
[i
] = NULL
;
2558 g_free(found_objects
);