/*! \brief Find an attribute in a list. * \par Function Description * Search for attribute by name. * * Counter is the n'th occurance of the attribute, and starts searching * from zero. Zero is the first occurance of an attribute. * * \param [in] list GList of attributes to search. * \param [in] name Character string with attribute name to search for. * \param [in] count Which occurance to return. * \return The n'th attribute object in the given list with the given name. */ OBJECT *o_attrib_find_attrib_by_name (const GList *list, char *name, int count) { OBJECT *a_current; const GList *iter; char *found_name; int internal_counter = 0; for (iter = list; iter != NULL; iter = g_list_next (iter)) { a_current = iter->data; g_return_val_if_fail (a_current->type == OBJ_TEXT, NULL); if (!o_attrib_get_name_value (a_current, &found_name, NULL)) continue; if (strcmp (name, found_name) == 0) { if (internal_counter == count) { g_free (found_name); return a_current; } internal_counter++; } g_free (found_name); } return NULL; }
/*! \brief check whether an object is a attributes * \par Function Description * This function checks if an object should be promoted. * An attribute object is promotable if it's promoted by default, or the user * has configered it to promote an attribute. * * \param [in] toplevel The TOPLEVEL object * \param [in] object The attribute object to check * \return TRUE if the object is a eligible attribute, FALSE otherwise */ static int o_complex_is_eligible_attribute (TOPLEVEL *toplevel, OBJECT *object) { char *name = NULL; int promotableAttribute = FALSE; /* always promote symversion= attribute, even if it is invisible */ if (strncmp(object->text->string, "symversion=", 11) == 0) return TRUE; /* check list against attributes which can be promoted */ if (toplevel->always_promote_attributes != NULL) { if (o_attrib_get_name_value (object, &name, NULL)) { if (g_list_find_custom(toplevel->always_promote_attributes, name, (GCompareFunc) strcmp) != NULL) { /* Name of the attribute was in the always promote attributes list */ promotableAttribute = TRUE; } g_free(name); if (promotableAttribute) return TRUE; } } /* object is invisible and we do not want to promote invisible text */ if ((!o_is_visible (toplevel, object)) && (toplevel->promote_invisible == FALSE)) return FALSE; /* attribute not eligible for promotion */ /* yup, attribute can be promoted */ return TRUE; }
/*! \brief Search list for partial string match. * \par Function Description * Search list for partial string match. * * Counter is the n'th occurance of the attribute, and starts searching * from zero. Zero is the first occurance of an attribute. * * \param [in] object The OBJECT list to search. * \param [in] search_for Partial character string to search for. * \param [in] counter Which occurance to return. * \return Matching object value if found, NULL otherwise. * * \warning * Caller must g_free returned character string. */ char *o_attrib_search_string_partial(OBJECT *object, char *search_for, int counter) { OBJECT *o_current; int val; int internal_counter=0; char *found_value = NULL; char *return_string = NULL; o_current = object; if (o_current == NULL) { return(NULL); } if (o_current->type == OBJ_TEXT) { if (strstr(o_current->text->string, search_for)) { if (counter != internal_counter) { internal_counter++; } else { val = o_attrib_get_name_value(o_current->text->string, NULL, &found_value); if (val) { return_string = g_strdup(found_value); g_free(found_value); return(return_string); } } } } g_free(found_value); return (NULL); }
/*! \brief Search attribute list by name. * \par Function Description * Search for attribute by name. * * Counter is the n'th occurance of the attribute, and starts searching * from zero. Zero is the first occurance of an attribute. * * \param [in] list GList of attributes to search. * \param [in] name Character string with attribute name to search for. * \param [in] counter Which occurance to return. * \return Character string with attribute value, NULL otherwise. */ static char *o_attrib_search_attrib_list_by_name (const GList *list, char *name, int counter) { OBJECT *attrib; char *value = NULL; attrib = o_attrib_find_attrib_by_name (list, name, counter); if (attrib != NULL) o_attrib_get_name_value (attrib, NULL, &value); return value; }
/*! \brief Search for attribute by value and name. * \par Function Description * Search for attribute by value and name. * * Counter is the n'th occurance of the attribute, and starts searching * from zero. Zero is the first occurance of an attribute. * * The value is the primary search key, but name is checked before * an OBJECT is returned to ensure the correct OBJECT has been found. * * \param [in] list The attribute OBJECT list to search. * \param [in] value Character string with value to search for. * \param [in] name Character string with name to compare. * \param [in] counter Which occurance to return. * \return The attribute OBJECT if found, NULL otherwise. * */ OBJECT *o_attrib_search_attrib_value(GList *list, char *value, char *name, int counter) { OBJECT *a_current; GList *a_iter; int val; int internal_counter=0; char *found_name = NULL; char *found_value = NULL; a_iter = list; if (!value) return(NULL); if (!name) return(NULL); while(a_iter != NULL) { a_current = a_iter->data; if (a_current->type == OBJ_TEXT) { val = o_attrib_get_name_value(a_current->text->string, &found_name, &found_value); if (val) { #if DEBUG printf("found value: %s\n", found_value); printf("looking for: %s\n", value); #endif if (strcmp(value, found_value) == 0) { if (counter != internal_counter) { internal_counter++; } else { if (strstr(found_name, name)) { g_free(found_name); g_free(found_value); return a_current; } } } if (found_name) { g_free(found_name); found_name = NULL; } if (found_value) { g_free(found_value); found_value = NULL; } } } a_iter = g_list_next (a_iter); } g_free(found_name); g_free(found_value); return (NULL); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_edit(GSCHEM_TOPLEVEL *w_current, GList *list) { OBJECT *o_current; const gchar *str = NULL; if (list == NULL) { w_current->inside_action = 0; i_set_state(w_current, SELECT); return; } o_current = (OBJECT *) list->data; if (o_current == NULL) { fprintf(stderr, _("Got an unexpected NULL in o_edit\n")); exit(-1); } /* for now deal with only the first item */ switch(o_current->type) { /* also add the ability to multi attrib edit: nets, busses, pins */ case(OBJ_COMPLEX): case(OBJ_PLACEHOLDER): case(OBJ_NET): case(OBJ_PIN): case(OBJ_BUS): x_multiattrib_open (w_current); break; case(OBJ_PICTURE): picture_change_filename_dialog(w_current); break; case(OBJ_ARC): arc_angle_dialog(w_current, o_current); break; case(OBJ_TEXT): str = o_text_get_string (w_current->toplevel, o_current); if (o_attrib_get_name_value (o_current, NULL, NULL) && /* attribute editor only accept 1-line values for attribute */ o_text_num_lines (str) == 1) { attrib_edit_dialog(w_current,o_current, FROM_MENU); } else { o_text_edit(w_current, o_current); } break; } /* has to be more extensive in the future */ /* some sort of redrawing? */ }
/*! \brief update the visible part of a string * \par Function Description * If a string is an attribute, then it is possible to hide * the name or the value part of the attribute string. * This functions updates the text->disp_string according * to the object->show_name_value settings * * \param [in] object The OBJECT to update */ static void update_disp_string (OBJECT *object) { char *name = NULL; char *value = NULL; TEXT *text = object->text; g_free (text->disp_string); if (o_attrib_get_name_value (object, &name, &value)) { switch (object->show_name_value) { case (SHOW_NAME_VALUE): text->disp_string = g_strdup (text->string); break; case (SHOW_NAME): if (name[0] != '\0') { text->disp_string = g_strdup (name); } else { g_critical ("Got an improper attribute: %1$s\n", text->string); text->disp_string = g_strdup ("invalid"); } break; case (SHOW_VALUE): if (value[0] != '\0') { text->disp_string = g_strdup(value); } else { g_critical ("Got an improper attribute: %1$s\n", text->string); text->disp_string = g_strdup ("invalid"); } break; } text->name = g_intern_string (name); /* free the strings allocated by o_attrib_get_name_value */ g_free(name); g_free(value); } else { text->disp_string = g_strdup (text->string); text->name = NULL; } }
/*! \brief Search for slot attribute. * \par Function Description * Search for slot attribute. * * The returned value will only come from an attached attribute. * * \param [in] object OBJECT list to search. * \param [in] return_found attached slot attribute if found, NULL otherwise. * \return Character string with attribute value, NULL otherwise. * * \warning * Caller must g_free returned character string */ char *s_slot_search_slot (OBJECT *object, OBJECT **return_found) { GList *attributes; OBJECT *attrib; char *value = NULL; attributes = o_attrib_return_attribs (object); attrib = o_attrib_find_attrib_by_name (attributes, "slot", 0); g_list_free (attributes); if (attrib != NULL) o_attrib_get_name_value (attrib, NULL, &value); if (return_found) *return_found = attrib; return value; }
/*! \brief Search TOPLEVEL attributes. * \par Function Description * This function should only be used to search for TOPLEVEL attributes. * \warning * The list is the top level list. Do not pass it an object_list list * unless you know what you are doing. * * Counter is the n'th occurance of the attribute, and starts searching * from zero. Zero is the first occurance of an attribute. * * \param [in] list The GList to search (TOPLEVEL only). * \param [in] name Character string of attribute name to search for. * \param [in] counter Which occurance to return. * \return Character string with attribute value, NULL otherwise. * * \warning * Caller must g_free returned character string. */ char *o_attrib_search_toplevel (const GList *list, char *name, int counter) { OBJECT *o_current; int val; int internal_counter=0; char *found_name = NULL; char *found_value = NULL; char *return_string = NULL; const GList *iter; iter = list; while (iter != NULL) { o_current = (OBJECT *)iter->data; /* search for attributes outside */ if (o_current->type == OBJ_TEXT) { val = o_attrib_get_name_value(o_current->text->string, &found_name, &found_value); if (val) { if (strcmp(name, found_name) == 0) { if (counter != internal_counter) { internal_counter++; } else { return_string = g_strdup (found_value); g_free(found_name); g_free(found_value); return(return_string); } } if (found_name) { g_free(found_name); found_name = NULL; } if (found_value) { g_free(found_value); found_value = NULL; } } } iter = g_list_next (iter); } g_free(found_name); g_free(found_value); return (NULL); }
/*! \brief Find all floating attributes in the given object list. * \par Function Description * Find all floating attributes in the given object list. * * \param [in] list GList of OBJECTs to search for floating attributes. * \return GList of floating attributes from the input list * * \warning * Caller must g_list_free returned list. */ GList *o_attrib_find_floating_attribs (const GList *list) { GList *floating_attributes = NULL; const GList *iter; OBJECT *o_current; for (iter = list; iter != NULL; iter = g_list_next (iter)) { o_current = iter->data; /* Skip non text objects, attached attributes and text which doesn't * constitute a valid attributes (e.g. general text placed on the page) */ if (o_current->type == OBJ_TEXT && o_current->attached_to == NULL && o_attrib_get_name_value (o_current, NULL, NULL)) { floating_attributes = g_list_prepend (floating_attributes, o_current); } } return g_list_reverse (floating_attributes); }
/*! \brief Get all attached attributes of the specified OBJECT. * \par Function Description * This function returns all attributes of the specified object. * * The returned GList should be freed using the #g_list_free(). * * This function aggregates the attached and inherited attributes * belonging to a given OBJECT. (inherited attributes are those * which live as toplevel un-attached attributes inside in a * complex OBJECT's prim_objs). * * \param [in] object OBJECT whos attributes to return. * \return A GList of attributes belinging to the passed object. */ GList * o_attrib_return_attribs (OBJECT *object) { GList *attribs = NULL; GList *inherited_attribs; OBJECT *a_current; GList *a_iter; g_return_val_if_fail (object != NULL, NULL); /* Directly attached attributes */ for (a_iter = object->attribs; a_iter != NULL; a_iter = g_list_next (a_iter)) { a_current = a_iter->data; if (a_current->type != OBJ_TEXT) continue; /* Don't add invalid attributes to the list */ if (!o_attrib_get_name_value (a_current, NULL, NULL)) continue; attribs = g_list_prepend (attribs, a_current); } attribs = g_list_reverse (attribs); /* Inherited attributes (inside complex objects) */ if (object->type == OBJ_COMPLEX || object->type == OBJ_PLACEHOLDER) { inherited_attribs = o_attrib_find_floating_attribs (object->complex->prim_objs); attribs = g_list_concat (attribs, inherited_attribs); } return attribs; }
/*! \brief Update component attributes in TOP_LEVEL * * For each attrib string attached to the component, update it using the value * held in new_comp_attrib_list. Algorithm: * -# Form list of all component attribs held on both the component * (o_current), as well as in the attrib list (SHEET_DATA). * -# Loop over name=value pairs held in complete_comp_attrib_list. * -# For each name=value pair, look for corresponding attrib on o_current. * -# For each name=value pair, look for the corresponding attrib in * new_comp_attrib_list. * -# If the attrib exists on o_current and in new_comp_attrib_list, write the * new value (from new_comp_attrib_list) into o_current. * -# If the attrib exists on o_current, but is null in name=value pair, * delete the attrib from o_current. * -# If the attribs doesn't exist on o_current, but is non-null in * the name=value pair, create an attrib object and add it to the part * on o_current. * \param toplevel TOPLEVEL structure * \param o_current Component (complex) to be updated. * \param new_comp_attrib_list list of name=value attribute pairs * from SHEET_DATA. */ void s_toplevel_update_component_attribs_in_toplevel ( TOPLEVEL *toplevel, OBJECT *o_current, STRING_LIST *new_comp_attrib_list) { STRING_LIST *local_list; STRING_LIST *complete_comp_attrib_list; char *old_name_value_pair; char *new_attrib_name; char *new_attrib_value; char *old_attrib_name; char *old_attrib_value; gchar *refdes; GList *a_iter; OBJECT *a_current; int count = 0; /* This is to fake out a function called later */ gint row, col; gint visibility = 0; gint show_name_value = 0; #if DEBUG printf("----- Entering s_toplevel_update_component_attribs_in_toplevel.\n"); #endif /* * To remove dead attribs from o_current, we need to form a complete list of unique * attribs by taking the union of the new attribs from the SHEET_DATA, and * the old attribs living on o_current. That's what we're doing here. * Later, we can delete those attribs in o_current which don't apear in * new_comp_attrib_list. */ /* First duplicate new_comp_attrib_list */ complete_comp_attrib_list = s_string_list_duplicate_string_list(new_comp_attrib_list); /* Now create a complete list of unique attribute names. This will be used in * the loop below when updating attributes. */ a_iter = o_current->attribs; while (a_iter != NULL) { a_current = a_iter->data; if (a_current->type == OBJ_TEXT && a_current->text != NULL) { /* found a name=value attribute pair. */ /* may need to check more thoroughly here. . . . */ old_name_value_pair = g_strdup(a_current->text->string); /* Else clause is suggestion from Ales */ #if 1 old_attrib_name = u_basic_breakup_string(old_name_value_pair, '=', 0); if ( (strcmp(old_attrib_name, "refdes") != 0) && (strcmp(old_attrib_name, "net") != 0) && (strcmp(old_attrib_name, "slot") != 0) && (s_attrib_name_in_list(new_comp_attrib_list, old_attrib_name) == FALSE) ) { s_string_list_add_item(complete_comp_attrib_list, &count, old_name_value_pair); } #else /* might now compile now, but this #if'd out branch isn't being built */ gint status; status = o_attrib_get_name_value (a_current, &old_attrib_name, &old_attrib_value); if (status == 0) { /* Don't put "refdes" or "slot" into list. Don't put old name=value pair into list if a new * one is already in there. */ if ( (strcmp(old_attrib_name, "refdes") != 0) && (strcmp(old_attrib_name, "net") != 0) && (strcmp(old_attrib_name, "slot") != 0) && (s_attrib_name_in_list(new_comp_attrib_list, old_attrib_name) == FALSE) ) { s_string_list_add_item(complete_comp_attrib_list, &count, old_name_value_pair); } g_free (old_attrib_name); g_free (old_attrib_value); } #endif g_free(old_name_value_pair); g_free(old_attrib_name); } a_iter = g_list_next (a_iter); } /* while (a_current != NULL) */ /* *Now the main business of this function: updating the attribs attached to this o_current. * Loop on name=value pairs held in complete_comp_attrib_list , and then use this to get the * name=value pairs out of new_comp_attrib_list and from o_current. */ /* First handle a special case: the component has no attribs (beside refdes). */ if (complete_comp_attrib_list->data == NULL) return; /* Now the normal case. . . . */ local_list = complete_comp_attrib_list; while (local_list != NULL) { #if DEBUG printf("\n\n"); printf(" In s_toplevel_update_component_attribs_in_toplevel, handling entry in complete list %s .\n", local_list->data); #endif /* Now get the old attrib name & value from complete_comp_attrib_list * and value from o_current */ old_attrib_name = u_basic_breakup_string(local_list->data, '=', 0); old_attrib_value = o_attrib_search_attached_attribs_by_name (o_current, old_attrib_name, 0); #if DEBUG printf(" In s_toplevel_update_component_attribs_in_toplevel, old name = \"%s\" .\n", old_attrib_name); printf(" In s_toplevel_update_component_attribs_in_toplevel, old value = \"%s\" .\n", old_attrib_value); #endif /* Next try to get this attrib from new_comp_attrib_list */ new_attrib_name = u_basic_breakup_string(local_list->data, '=', 0); if (s_string_list_in_list(new_comp_attrib_list, local_list->data)) { new_attrib_value = s_misc_remaining_string(local_list->data, '=', 1); } else { new_attrib_value = NULL; } #if DEBUG printf(" In s_toplevel_update_component_attribs_in_toplevel, new name = \"%s\" .\n", new_attrib_name); printf(" In s_toplevel_update_component_attribs_in_toplevel, new value = \"%s\" .\n", new_attrib_value); #endif /* Now get row and col where this new attrib lives. Then get * visibility of the new attrib stored in the component table */ /* We'll need this later */ refdes = g_strdup(s_attrib_get_refdes(o_current)); row = s_table_get_index(sheet_head->master_comp_list_head, refdes); col = s_table_get_index(sheet_head->master_comp_attrib_list_head, new_attrib_name); /* if attribute has been deleted from the sheet, here is where we detect that */ if ( (row == -1) || (col == -1) ) { new_attrib_value = NULL; /* attrib will be deleted below */ } else { /* we need a better place to get this info since the TABLE can be out of date */ visibility = sheet_head->component_table[row][col].visibility; show_name_value = sheet_head->component_table[row][col].show_name_value; } g_free(refdes); /* ------- Four cases to consider: Case 1 ----- */ if ( (old_attrib_value != NULL) && (new_attrib_value != NULL) && (strlen(new_attrib_value) != 0) ) { /* simply write new attrib into place of old one. */ #if DEBUG printf(" -- In s_toplevel_update_component_attribs_in_toplevel,\n"); printf(" about to replace old attrib with name= %s, value= %s\n", new_attrib_name, new_attrib_value); printf(" visibility = %d, show_name_value = %d.\n", visibility, show_name_value); #endif s_object_replace_attrib_in_object(toplevel, o_current, new_attrib_name, new_attrib_value, visibility, show_name_value); } /* ------- Four cases to consider: Case 2 ----- */ else if ( (old_attrib_value != NULL) && (new_attrib_value == NULL) ) { /* remove attrib from component*/ #if DEBUG printf(" -- In s_toplevel_update_component_attribs_in_toplevel, about to remove old attrib with name= %s, value= %s\n", old_attrib_name, old_attrib_value); #endif s_object_remove_attrib_in_object (toplevel, o_current, old_attrib_name); } /* ------- Four cases to consider: Case 3 ----- */ else if ( (old_attrib_value == NULL) && (new_attrib_value != NULL) ) { /* add new attrib to component. */ #if DEBUG printf(" -- In s_toplevel_update_component_attribs_in_toplevel, about to add new attrib with name= %s, value= %s\n", new_attrib_name, new_attrib_value); #endif s_object_add_comp_attrib_to_object (toplevel, o_current, new_attrib_name, new_attrib_value, visibility, show_name_value); /* ------- Four cases to consider: Case 4 ----- */ } else { /* Do nothing. */ #if DEBUG printf(" -- In s_toplevel_update_component_attribs_in_toplevel, nothing needs to be done.\n"); #endif } /* Toggle attribute visibility and name/value setting */ /* free everything and iterate */ g_free(new_attrib_name); g_free(new_attrib_value); g_free(old_attrib_name); g_free(old_attrib_value); local_list = local_list->next; } /* while (local_list != NULL) */ return; }
/*! \brief Search for attibute by name. * \par Function Description * Search for attribute by name. * * \warning * The list is the top level list. Do not pass it an object_list list * unless you know what you are doing. * * Counter is the n'th occurance of the attribute, and starts searching * from zero. Zero is the first occurance of an attribute. * * \param [in] list GList to search. * \param [in] name Character string with attribute name to search for. * \param [in] counter Which occurance to return. * \return Character string with attribute value, NULL otherwise. * * \warning * Caller must g_free returned character string. */ char *o_attrib_search_name (const GList *list, char *name, int counter) { OBJECT *o_current; OBJECT *a_current; GList *a_iter; int val; int internal_counter=0; char *found_name = NULL; char *found_value = NULL; char *return_string = NULL; const GList *iter; iter = list; while (iter != NULL) { o_current = (OBJECT *)iter->data; if (o_current->attribs != NULL) { a_iter = o_current->attribs; while(a_iter != NULL) { a_current = a_iter->data; if (a_current->type == OBJ_TEXT) { val = o_attrib_get_name_value(a_current->text->string, &found_name, &found_value); if (val) { if (strcmp(name, found_name) == 0) { if (counter != internal_counter) { internal_counter++; } else { return_string = g_strdup (found_value); g_free(found_name); g_free(found_value); return(return_string); } } if (found_name) { g_free(found_name); found_name = NULL; } if (found_value) { g_free(found_value); found_value = NULL; } } #if DEBUG printf("0 _%s_\n", a_current->text->string); printf("1 _%s_\n", found_name); printf("2 _%s_\n", found_value); #endif } a_iter = g_list_next (a_iter); } } /* search for attributes outside */ if (o_current->type == OBJ_TEXT) { g_free(found_name); g_free(found_value); val = o_attrib_get_name_value(o_current->text->string, &found_name, &found_value); if (val) { if (strcmp(name, found_name) == 0) { if (counter != internal_counter) { internal_counter++; } else { return_string = g_strdup (found_value); g_free(found_name); g_free(found_value); return(return_string); } } if (found_name) { g_free(found_name); found_name = NULL; } if (found_value) { g_free(found_value); found_value = NULL; } } } iter = g_list_next (iter); } g_free(found_name); g_free(found_value); return (NULL); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_slot_end(GSCHEM_TOPLEVEL *w_current, const char *string, int len) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *new_obj; OBJECT *object; OBJECT *temp; char *slot_value; char *numslots_value; OBJECT *slot_text_object; char *value = NULL; int numslots; int new_slot_number; int status; status = o_attrib_get_name_value(string, NULL, &value); if (!status) { s_log_message(_("Slot attribute malformed\n")); return; } object = o_select_return_first_object(w_current); /* get the parent object if the selection is only a text object */ if (object != NULL && object->type == OBJ_TEXT) { if (object->attached_to != NULL) { object = object->attached_to; } } /* now find the slot attribute on the outside first */ if (object != NULL) { numslots_value = o_attrib_search_numslots(object, NULL); if (!numslots_value) { s_log_message(_("numslots attribute missing\n")); s_log_message( _("Slotting not allowed for this component\n")); g_free(value); return; } numslots = atoi(numslots_value); g_free(numslots_value); new_slot_number = atoi(value); #if DEBUG printf("numslots = %d\n", numslots); #endif if (new_slot_number > numslots || new_slot_number <=0 ) { s_log_message(_("New slot number out of range\n")); g_free(value); return; } /* first see if slot attribute already exists outside * complex */ slot_value = o_attrib_search_slot(object, &slot_text_object); if (slot_value) { o_text_set_string (toplevel, slot_text_object, string); temp = slot_text_object; if (temp->visibility == VISIBLE || (temp->visibility == INVISIBLE && toplevel->show_hidden_text)) { o_invalidate (w_current,temp); } o_text_recreate(toplevel, temp); /* this doesn't deal with the selection list * item */ if (temp->visibility == VISIBLE || (temp->visibility == INVISIBLE && toplevel->show_hidden_text)) { o_invalidate (w_current,temp); } g_free(slot_value); } else { /* here you need to do the add the slot attribute since it doesn't exist */ new_obj = o_text_new (toplevel, OBJ_TEXT, ATTRIBUTE_COLOR, object->complex->x, object->complex->y, LOWER_LEFT, 0, /* zero is angle */ string, 10, INVISIBLE, SHOW_NAME_VALUE); s_page_append (toplevel->page_current, new_obj); /* manually attach attribute */ o_attrib_attach (toplevel, new_obj, object, FALSE); slot_text_object = new_obj; } o_invalidate (w_current, object); o_attrib_slot_update(toplevel, object); o_invalidate (w_current,object); toplevel->page_current->CHANGED = 1; g_free(value); } else { fprintf(stderr, _("uggg! you tried to slot edit something that doesn't exist!\n")); g_free(value); exit(-1); } }
/* given a net name, an attribute, and a wanted attribute, return all the given attribute of all the graphical objects connected to that net name */ SCM g_graphical_objs_in_net_with_attrib_get_attrib (SCM scm_netname, SCM scm_has_attribute, SCM scm_wanted_attribute) { SCM list = SCM_EOL; NETLIST *nl_current; CPINLIST *pl_current; char *wanted_net_name; char *wanted_attrib; char *has_attrib; char *net_name; char *attrib_value=NULL; char *has_attrib_value = NULL; char *has_attrib_name = NULL; SCM_ASSERT(scm_is_string (scm_netname), scm_netname, SCM_ARG1, "gnetlist:get-attr-of-conn-graph-objs-with-attr"); SCM_ASSERT(scm_is_string (scm_wanted_attribute), scm_wanted_attribute, SCM_ARG2, "gnetlist:get-attr-of-conn-graph-objs-with-attr"); SCM_ASSERT(scm_is_string (scm_has_attribute), scm_has_attribute, SCM_ARG3, "gnetlist:get-attr-of-conn-graph-objs-with-attr"); wanted_net_name = SCM_STRING_CHARS (scm_netname); wanted_attrib = SCM_STRING_CHARS (scm_wanted_attribute); has_attrib = SCM_STRING_CHARS (scm_has_attribute); if (wanted_net_name == NULL) { return list; } nl_current = graphical_netlist_head; /* walk through the list of components, and through the list * of individual pins on each, adding net names to the list * being careful to ignore duplicates, and unconnected pins */ while (nl_current != NULL) { pl_current = nl_current->cpins; while (pl_current != NULL) { if (pl_current->net_name) { net_name = pl_current->net_name; if (strcmp(net_name, wanted_net_name) == 0) { if (o_attrib_get_name_value (has_attrib, &has_attrib_name, &has_attrib_value) != 0) { attrib_value = o_attrib_search_name_single(nl_current->object_ptr, has_attrib_name, NULL); if ( ((has_attrib_value == NULL) && (attrib_value == NULL)) || ((has_attrib_value != NULL) && (attrib_value != NULL) && (strcmp(attrib_value, has_attrib_value) == 0)) ) { g_free (attrib_value); attrib_value = o_attrib_search_name_single(nl_current->object_ptr, wanted_attrib, NULL); if (attrib_value) { list = scm_cons (scm_makfrom0str (attrib_value), list); } g_free (attrib_value); } g_free (has_attrib_name); g_free (has_attrib_value); } } } pl_current = pl_current->next; } nl_current = nl_current->next; } return list; }
/*! \brief Search for first occurance of a named attribute. * \par Function Description * Search for first occurance of a named attribute. * * \param [in] object The OBJECT list to search. * \param [in] name Character string of attribute name to search for. * \param [out] return_found Contains attribute OBJECT if found, NULL otherwise. * \return Character string with attribute value, NULL otherwise. * * \warning * Caller must g_free returned character string. */ char *o_attrib_search_name_single(OBJECT *object, char *name, OBJECT **return_found) { OBJECT *o_current; OBJECT *a_current; GList *a_iter; int val; char *found_name = NULL; char *found_value = NULL; char *return_string = NULL; o_current = object; if (o_current == NULL) { return(NULL); } if (o_current->attribs != NULL) { a_iter = o_current->attribs; while(a_iter != NULL) { a_current = a_iter->data; if (a_current->type == OBJ_TEXT) { val = o_attrib_get_name_value(a_current->text->string, &found_name, &found_value); if (val) { if (strcmp(name, found_name) == 0) { return_string = g_strdup (found_value); if (return_found) { *return_found = a_current; } g_free(found_name); g_free(found_value); return(return_string); } if (found_name) { g_free(found_name); found_name = NULL; } if (found_value) { g_free(found_value); found_value = NULL; } } #if DEBUG printf("0 _%s_\n", found->text->string); printf("1 _%s_\n", found_name); printf("2 _%s_\n", found_value); #endif } a_iter = g_list_next (a_iter); } } /* search for attributes outside */ if (o_current->type == OBJ_TEXT) { g_free(found_name); g_free(found_value); val = o_attrib_get_name_value(o_current->text->string, &found_name, &found_value); if (val) { if (strcmp(name, found_name) == 0) { return_string = g_strdup (found_value); if (return_found) { *return_found = o_current; } g_free(found_name); g_free(found_value); return(return_string); } if (found_name) { g_free(found_name); found_name = NULL; } if (found_value) { g_free(found_value); found_value = NULL; } } } if (return_found) { *return_found = NULL; } g_free(found_name); g_free(found_value); return (NULL); }
/*! \brief Update a component. * * \par Function Description * Updates \a o_current to the latest version of the symbol available * in the symbol library, while preserving any attributes set in the * current schematic. On success, returns the new OBJECT which * replaces \a o_current on the page; \a o_current is deleted. On * failure, returns NULL, and \a o_current is left unchanged. * * \param [in] w_current The GSCHEM_TOPLEVEL object. * \param [in,out] o_current The OBJECT to be updated. * * \return the new OBJECT that replaces \a o_current. */ OBJECT * o_update_component (GSCHEM_TOPLEVEL *w_current, OBJECT *o_current) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *o_new; PAGE *page; GList *new_attribs; GList *old_attribs; GList *iter; const CLibSymbol *clib; g_return_val_if_fail (o_current != NULL, NULL); g_return_val_if_fail (o_current->type == OBJ_COMPLEX, NULL); g_return_val_if_fail (o_current->complex_basename != NULL, NULL); page = o_get_page (toplevel, o_current); /* This should be replaced with API to invalidate only the specific * symbol name we want to update */ s_clib_flush_symbol_cache (); clib = s_clib_get_symbol_by_name (o_current->complex_basename); if (clib == NULL) { s_log_message (_("Could not find symbol [%s] in library. Update failed.\n"), o_current->complex_basename); return NULL; } /* Unselect the old object. */ o_selection_remove (toplevel, page->selection_list, o_current); /* Create new object and set embedded */ o_new = o_complex_new (toplevel, OBJ_COMPLEX, DEFAULT_COLOR, o_current->complex->x, o_current->complex->y, o_current->complex->angle, o_current->complex->mirror, clib, o_current->complex_basename, 1); if (o_complex_is_embedded (o_current)) { o_embed (toplevel, o_new); } new_attribs = o_complex_promote_attribs (toplevel, o_new); /* Cull any attributes from new COMPLEX that are already attached to * old COMPLEX. Note that the new_attribs list is kept consistent by * setting GList data pointers to NULL if their OBJECTs are * culled. At the end, the new_attribs list is updated by removing * all list items with NULL data. This is slightly magic, but * works. */ for (iter = new_attribs; iter != NULL; iter = g_list_next (iter)) { OBJECT *attr_new = iter->data; gchar *name; gchar *value; g_assert (attr_new->type == OBJ_TEXT); o_attrib_get_name_value (attr_new, &name, NULL); value = o_attrib_search_attached_attribs_by_name (o_current, name, 0); if (value != NULL) { o_attrib_remove (toplevel, &o_new->attribs, attr_new); s_delete_object (toplevel, attr_new); iter->data = NULL; } g_free (name); g_free (value); } new_attribs = g_list_remove_all (new_attribs, NULL); /* Detach attributes from old OBJECT and attach to new OBJECT */ old_attribs = g_list_copy (o_current->attribs); o_attrib_detach_all (toplevel, o_current); o_attrib_attach_list (toplevel, old_attribs, o_new, 1); g_list_free (old_attribs); /* Add new attributes to page */ s_page_append_list (toplevel, page, new_attribs); /* Update pinnumbers for current slot */ s_slot_update_object (toplevel, o_new); /* Replace old OBJECT with new OBJECT */ s_page_replace (toplevel, page, o_current, o_new); s_delete_object (toplevel, o_current); /* Select new OBJECT */ o_selection_add (toplevel, page->selection_list, o_new); /* mark the page as modified */ toplevel->page_current->CHANGED = 1; o_undo_savestate (w_current, UNDO_ALL); return o_new; }
/*! \brief Get the object bounds of the given object, excluding the object * types given as parameters. * \par Function Description * Get the object bounds without considering the attributes in * exclude_attrib_list, neither the object types included in * exclude_obj_type_list * \param [in] toplevel TOPLEVEL structure. * \param [in] o_current The object we want to know the bounds of. * \param [in] exclude_attrib_list A list with the attribute names we don't * want to include when calculing the bounds. * \param [in] exclude_obj_type_list A list with the object types we don't * want to include when calculing the bounds. * The object types are those used in (OBJECT *)->type converted into strings. * \param [out] left Left bound of the object. * \param [out] top Top bound of the object. * \param [out] right Right bound of the object. * \param [out] bottom Bottom bound of the object. * */ static void custom_world_get_single_object_bounds (TOPLEVEL *toplevel, OBJECT *o_current, int *left, int *top, int *right, int *bottom, GList *exclude_attrib_list, GList *exclude_obj_type_list) { OBJECT *obj_ptr = NULL; OBJECT *a_current; GList *a_iter; int rleft, rright, rbottom, rtop; const gchar *text_value; char *name_ptr, aux_ptr[2]; gboolean include_text; *left = rleft = toplevel->init_right; *top = rtop = toplevel->init_bottom;; *right = *bottom = rright = rbottom = 0; obj_ptr = o_current; sprintf(aux_ptr, "%c", obj_ptr->type); include_text = TRUE; if (!g_list_find_custom(exclude_obj_type_list, aux_ptr, (GCompareFunc) &strcmp)) { switch(obj_ptr->type) { case (OBJ_PIN): world_get_single_object_bounds (toplevel, obj_ptr, &rleft, &rtop, &rright, &rbottom); break; case (OBJ_TEXT): text_value = o_text_get_string (toplevel, obj_ptr); if (text_value) { if (o_attrib_get_name_value(text_value, &name_ptr, NULL) && g_list_find_custom(exclude_attrib_list, name_ptr, (GCompareFunc) &strcmp)) { include_text = FALSE; } if (g_list_find_custom(exclude_attrib_list, "all", (GCompareFunc) &strcmp)) { include_text = FALSE; } if (include_text) { world_get_single_object_bounds (toplevel, obj_ptr, &rleft, &rtop, &rright, &rbottom); } g_free(name_ptr); } break; case (OBJ_COMPLEX): case (OBJ_PLACEHOLDER): custom_world_get_object_glist_bounds (toplevel, o_current->complex->prim_objs, left, top, right, bottom, exclude_attrib_list, exclude_obj_type_list); break; default: world_get_single_object_bounds (toplevel, obj_ptr, &rleft, &rtop, &rright, &rbottom); break; } if (rleft < *left) *left = rleft; if (rtop < *top) *top = rtop; if (rright > *right) *right = rright; if (rbottom > *bottom) *bottom = rbottom; /* If it's a pin object, check the pin attributes */ if (obj_ptr->type == OBJ_PIN) { a_iter = obj_ptr->attribs; while (a_iter != NULL) { a_current = a_iter->data; if (a_current->type == OBJ_TEXT) { custom_world_get_single_object_bounds(toplevel, a_current, &rleft, &rtop, &rright, &rbottom, exclude_attrib_list, exclude_obj_type_list); if (rleft < *left) *left = rleft; if (rtop < *top) *top = rtop; if (rright > *right) *right = rright; if (rbottom > *bottom) *bottom = rbottom; } a_iter = g_list_next (a_iter); } } } }