/*! \brief Find all text objects that match a pattern * * \param pages the list of pages to search * \param text the pattern to match * \return a list of objects that match the given pattern */ static GSList* find_objects_using_pattern (GSList *pages, const char *text) { GSList *object_list = NULL; GSList *page_iter = pages; GPatternSpec *pattern; g_return_val_if_fail (text != NULL, NULL); pattern = g_pattern_spec_new (text); while (page_iter != NULL) { const GList *object_iter; PAGE *page = (PAGE*) page_iter->data; page_iter = g_slist_next (page_iter); if (page == NULL) { g_warning ("NULL page encountered"); continue; } object_iter = s_page_objects (page); while (object_iter != NULL) { OBJECT *object = (OBJECT*) object_iter->data; const char *str; object_iter = g_list_next (object_iter); if (object == NULL) { g_warning ("NULL object encountered"); continue; } if (object->type != OBJ_TEXT) { continue; } if (!(o_is_visible (page->toplevel, object) || page->toplevel->show_hidden_text)) { continue; } str = geda_text_object_get_string (object); if (str == NULL) { g_warning ("NULL string encountered"); continue; } if (g_pattern_match_string (pattern, str)) { object_list = g_slist_prepend (object_list, object); } } } g_pattern_spec_free (pattern); return g_slist_reverse (object_list); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_edit_show_specific_text (GSCHEM_TOPLEVEL *w_current, const GList *o_list, char *stext) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *o_current; const GList *iter; iter = o_list; while (iter != NULL) { o_current = (OBJECT *)iter->data; if (o_current->type == OBJ_TEXT) { const gchar *str = o_text_get_string (w_current->toplevel, o_current); if (!strncmp (stext, str, strlen (stext))) { if (!o_is_visible (toplevel, o_current)) { o_set_visibility (toplevel, o_current, VISIBLE); o_text_recreate(toplevel, o_current); toplevel->page_current->CHANGED = 1; } } } iter = g_list_next (iter); } o_undo_savestate(w_current, UNDO_ALL); }
/*! \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 Change visibility status of attribute object. * \par Function Description * This function toggles the visibility status of the attribute \a * object and updates it. The object is erased or redrawn if * necessary. * * \param [in] w_current The GschemToplevel object. * \param [in] object The attribute object. */ void o_attrib_toggle_visibility(GschemToplevel *w_current, OBJECT *object) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); g_return_if_fail (object != NULL && object->type == OBJ_TEXT); if (o_is_visible (object)) { /* only erase if we are not showing hidden text */ if (!toplevel->show_hidden_text) { o_invalidate (w_current, object); } o_set_visibility (toplevel, object, INVISIBLE); if (toplevel->show_hidden_text) { /* draw text so that little I is drawn */ o_invalidate (w_current, object); } } else { /* if we are in the special show hidden mode, then erase text first */ /* to get rid of the little I */ if (toplevel->show_hidden_text) { o_invalidate (w_current, object); } o_set_visibility (toplevel, object, VISIBLE); o_text_recreate(toplevel, object); } gschem_toplevel_page_content_changed (w_current, toplevel->page_current); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_edit_show_specific_text (GschemToplevel *w_current, const GList *o_list, const char *stext) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); OBJECT *o_current; const GList *iter; iter = o_list; while (iter != NULL) { o_current = (OBJECT *)iter->data; if (o_current->type == OBJ_TEXT) { const gchar *str = o_text_get_string (w_current->toplevel, o_current); if (!strncmp (stext, str, strlen (stext))) { if (!o_is_visible (toplevel, o_current)) { o_set_visibility (toplevel, o_current, VISIBLE); o_text_recreate(toplevel, o_current); gschem_toplevel_page_content_changed (w_current, toplevel->page_current); } } } iter = g_list_next (iter); } o_undo_savestate_old(w_current, UNDO_ALL); }
/*! \brief Tests a if a given OBJECT was hit at a given set of coordinates * * \par Function Description * Tests a if a given OBJECT was hit at a given set of coordinates. If an * object is not selectable (e.g. it is locked), or it is invisible and * not being rendered, this function will return FALSE. * * \param [in] w_current The GschemToplevel object. * \param [in] object The OBJECT being hit-tested. * \param [in] w_x The X coordinate to test (in world coords). * \param [in] w_y The Y coordinate to test (in world coords). * \param [in] w_slack The slack applied to the hit-test. * * \returns TRUE if the OBJECT was hit, otherwise FALSE. */ static gboolean is_object_hit (GschemToplevel *w_current, OBJECT *object, int w_x, int w_y, int w_slack) { int left, top, right, bottom; if (!object->selectable) return FALSE; /* We can't hit invisible (text) objects unless show_hidden_text is active. */ if (!o_is_visible (object) && !w_current->toplevel->show_hidden_text) return FALSE; /* Do a coarse test first to avoid computing distances for objects ouside * of the hit range. */ if (!world_get_single_object_bounds(w_current->toplevel, object, &left, &top, &right, &bottom) || !inside_region (left - w_slack, top - w_slack, right + w_slack, bottom + w_slack, w_x, w_y)) return FALSE; return (o_shortest_distance (w_current->toplevel, object, w_x, w_y) < w_slack); }
/*! \brief Return the bounds of the given object. * \par Given an object, calculate the bounds coordinates. * \param [in] toplevel The toplevel structure. * \param [in] o_current The object to look the bounds for. * \param [out] rleft pointer to the left coordinate of the object. * \param [out] rtop pointer to the top coordinate of the object. * \param [out] rright pointer to the right coordinate of the object. * \param [out] rbottom pointer to the bottom coordinate of the object. * \return If any bounds were found for the object * \retval 0 No bound was found * \retval 1 Bound was found */ int world_get_single_object_bounds(TOPLEVEL *toplevel, OBJECT *o_current, int *rleft, int *rtop, int *rright, int *rbottom) { if (o_current != NULL) { switch(o_current->type) { case(OBJ_TEXT): /* only do bounding boxes for visible or doing show_hidden_text*/ /* you might lose some attrs though */ if (! (o_is_visible (toplevel, o_current) || toplevel->show_hidden_text)) { return 0; } /* This case falls through intentionally */ case(OBJ_LINE): case(OBJ_NET): case(OBJ_BUS): case(OBJ_BOX): case(OBJ_PICTURE): case(OBJ_CIRCLE): case(OBJ_PATH): case(OBJ_PIN): case(OBJ_ARC): case(OBJ_COMPLEX): case(OBJ_PLACEHOLDER): if (!o_current->w_bounds_valid) { o_recalc_single_object (toplevel, o_current); if (!o_current->w_bounds_valid) { return 0; } } *rleft = o_current->w_left; *rtop = o_current->w_top; *rright = o_current->w_right; *rbottom = o_current->w_bottom; return 1; default: break; } } return 0; }
/*! \brief Remove invisible attributes of an object from the selection list. * \par Function Description * * Remove all invisible attributes attached to the given object * from the selection list. If hidden text is being shown, this * function returns immediately. * * \param [in] w_current The GschemToplevel object. * \param [in,out] selection The SELECTION list to remove from. * \param [in] object The OBJECT whose invisible attributes to remove. */ void o_attrib_deselect_invisible (GschemToplevel *w_current, SELECTION *selection, OBJECT *selected) { OBJECT *a_current; GList *a_iter; g_assert( selection != NULL ); if (w_current->toplevel->show_hidden_text) { return; } for (a_iter = selected->attribs; a_iter != NULL; a_iter = g_list_next (a_iter)) { a_current = a_iter->data; if (a_current->selected && !o_is_visible(a_current)) { o_selection_remove (w_current->toplevel, selection, a_current); } } }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_edit_show_hidden_lowlevel (GSCHEM_TOPLEVEL *w_current, const GList *o_list) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *o_current; const GList *iter; iter = o_list; while (iter != NULL) { o_current = (OBJECT *)iter->data; if (o_current->type == OBJ_TEXT && !o_is_visible (toplevel, o_current)) { /* don't toggle the visibility flag */ o_text_recreate (toplevel, o_current); } if (o_current->type == OBJ_COMPLEX || o_current->type == OBJ_PLACEHOLDER) { o_edit_show_hidden_lowlevel(w_current, o_current->complex->prim_objs); o_recalc_single_object(toplevel, o_current); } iter = g_list_next (iter); } }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_edit_show_hidden_lowlevel (GschemToplevel *w_current, const GList *o_list) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); OBJECT *o_current; const GList *iter; iter = o_list; while (iter != NULL) { o_current = (OBJECT *)iter->data; if (o_current->type == OBJ_TEXT && !o_is_visible (toplevel, o_current)) { /* don't toggle the visibility flag */ o_text_recreate (toplevel, o_current); } if (o_current->type == OBJ_COMPLEX || o_current->type == OBJ_PLACEHOLDER) { o_edit_show_hidden_lowlevel(w_current, o_current->complex->prim_objs); o_current->w_bounds_valid_for = NULL; } iter = g_list_next (iter); } }
/*! \brief Add components to the component table * * This fcn iterates over adds all * objects found on this page looking * for components. When it finds a component, it finds all component * attribs and sticks them in the TABLE. * \param obj_list pointer to GList containing objects on this page */ void s_table_add_toplevel_comp_items_to_comp_table (const GList *obj_list) { gchar *temp_uref; int row, col; gchar *attrib_text; gchar *attrib_name; gchar *attrib_value; const GList *o_iter; GList *a_iter; OBJECT *a_current; gint old_visibility, old_show_name_value; if (verbose_mode) { printf("- Starting internal component TABLE creation\n"); } #ifdef DEBUG fflush(stderr); fflush(stdout); printf("=========== Just entered s_table_add_toplevel_comp_items_to_comp_table! ==============\n"); #endif /* ----- Iterate through all objects found on page ----- */ for (o_iter = obj_list; o_iter != NULL; o_iter = g_list_next (o_iter)) { OBJECT *o_current = o_iter->data; #ifdef DEBUG printf(" ---> In s_table_add_toplevel_comp_items_to_comp_table, examining o_current->name = %s\n", o_current->name); #endif /* ----- Now process objects found on page ----- */ if (o_current->type == OBJ_COMPLEX && o_current->attribs != NULL) { /* ---- Don't process part if it lacks a refdes ----- */ temp_uref = g_strdup(s_attrib_get_refdes(o_current)); if (temp_uref) { #if DEBUG printf(" In s_table_add_toplevel_comp_items_to_comp_table, found component on page. Refdes = %s\n", temp_uref); #endif verbose_print(" C"); /* Having found a component, we loop over all attribs in this * component, and stick them * into cells in the table. */ 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 an attribute */ /* may need to check more thoroughly here. . . . */ attrib_text = g_strdup(a_current->text->string); attrib_name = u_basic_breakup_string(attrib_text, '=', 0); attrib_value = s_misc_remaining_string(attrib_text, '=', 1); old_visibility = o_is_visible (pr_current, a_current) ? VISIBLE : INVISIBLE; old_show_name_value = a_current->show_name_value; /* Don't include "refdes" or "slot" because they form the row name. */ /* Also don't include "net" per bug found by Steve W. 4.3.2007 -- SDB */ if ( (strcmp(attrib_name, "refdes") != 0) && (strcmp(attrib_name, "net") != 0) && (strcmp(attrib_name, "slot") != 0) ) { /* Get row and col where to put this attrib */ row = s_table_get_index(sheet_head->master_comp_list_head, temp_uref); col = s_table_get_index(sheet_head->master_comp_attrib_list_head, attrib_name); /* Sanity check */ if (row == -1 || col == -1) { /* we didn't find the item in the table */ fprintf (stderr, "In s_table_add_toplevel_comp_items_to_comp_table, we didn't find either row or col in the lists!\n"); } else { #if DEBUG printf(" In s_table_add_toplevel_comp_items_to_comp_table, about to add row %d, col %d, attrib_value = %s\n", row, col, attrib_value); printf(" . . . current address of attrib_value cell is [%p]\n", &((sheet_head->component_table)[row][col]).attrib_value); #endif /* Is there a compelling reason for me to put this into a separate fcn? */ ((sheet_head->component_table)[row][col]).row = row; ((sheet_head->component_table)[row][col]).col = col; ((sheet_head->component_table)[row][col]).row_name = g_strdup(temp_uref); ((sheet_head->component_table)[row][col]).col_name = g_strdup(attrib_name); ((sheet_head->component_table)[row][col]).attrib_value = g_strdup(attrib_value); ((sheet_head->component_table)[row][col]).visibility = old_visibility; ((sheet_head->component_table)[row][col]).show_name_value = old_show_name_value; } } g_free(attrib_name); g_free(attrib_text); g_free(attrib_value); } a_iter = g_list_next (a_iter); } /* while (a_current != NULL) */ g_free(temp_uref); } /* if (temp_uref) */ } /* if (o_current->type == OBJ_COMPLEX) */ } verbose_done(); }
/*! \brief Find all text objects that match a regex * * \param pages the list of pages to search * \param text the regex to match * \return a list of objects that match the given regex */ static GSList* find_objects_using_regex (GSList *pages, const char *text, GError **error) { GError *ierror = NULL; GSList *object_list = NULL; GSList *page_iter = pages; GRegex *regex; g_return_val_if_fail (text != NULL, NULL); regex = g_regex_new (text, (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, &ierror); if (ierror != NULL) { g_propagate_error (error, ierror); return NULL; } while (page_iter != NULL) { const GList *object_iter; PAGE *page = (PAGE*) page_iter->data; page_iter = g_slist_next (page_iter); if (page == NULL) { g_warning ("NULL page encountered"); continue; } object_iter = s_page_objects (page); while (object_iter != NULL) { OBJECT *object = (OBJECT*) object_iter->data; const char *str; object_iter = g_list_next (object_iter); if (object == NULL) { g_warning ("NULL object encountered"); continue; } if (object->type != OBJ_TEXT) { continue; } if (!(o_is_visible (page->toplevel, object) || page->toplevel->show_hidden_text)) { continue; } str = geda_text_object_get_string (object); if (str == NULL) { g_warning ("NULL string encountered"); continue; } if (g_regex_match (regex, str, (GRegexMatchFlags) 0, NULL)) { object_list = g_slist_prepend (object_list, object); } } } g_regex_unref (regex); return g_slist_reverse (object_list); }