/*! \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); }
/*! \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); }
/* Makes a list of all attributes currently connected to object. * * Principle stolen from o_attrib_return_attribs */ SCM g_make_attrib_smob_list(GSCHEM_TOPLEVEL *w_current, OBJECT *object) { OBJECT *a_current; GList *a_iter; SCM smob_list = SCM_EOL; if (!object) { return(SCM_EOL); } if (!object->attribs) { return(SCM_EOL); } /* go through attribs */ a_iter = object->attribs; while(a_iter != NULL) { a_current = a_iter->data; if (a_current->type == OBJ_TEXT) { if (o_text_get_string (w_current->toplevel, a_current)) { smob_list = scm_cons (g_make_attrib_smob (w_current->toplevel, a_current), smob_list); } } a_iter = g_list_next (a_iter); } return smob_list; }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_text_edit(GschemToplevel *w_current, OBJECT *o_current) { /* you need to check to make sure only one object is selected */ /* no actually this is okay... not here in o_edit */ text_edit_dialog(w_current, o_text_get_string (w_current->toplevel, o_current), o_current->text->size, o_current->text->alignment); }
/*! \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 Function to test, whether the OBJECT matches the autotext criterias * \par Function Description * The criterias are those of the autonumber text dialog. The function decides * whether the <B>OBJECT</B> has to be renumberd, ignored or taken care of when * renumbering all other objects. * \return one of these integer values: <B>AUTONUMBER_IGNORE</B>, * <B>AUTONUMBER_RESPECT</B> or <B>AUTONUMBER_RENUMBER</B> and the current number * of the text object in <B>*number</B>. */ gint autonumber_match(AUTONUMBER_TEXT *autotext, OBJECT *o_current, gint *number) { gint i, len, isnumbered=1; const gchar *str = NULL; len = strlen(autotext->current_searchtext); /* first find out whether we can ignore that object */ if (o_current->type != OBJ_TEXT) /* text object */ return AUTONUMBER_IGNORE; str = o_text_get_string (autotext->w_current->toplevel, o_current); if (!(strlen(str) - len > 0) || !g_str_has_prefix(str, autotext->current_searchtext)) return AUTONUMBER_IGNORE; /* the string object matches with its leading characters to the searchtext */ /* now look for the extension, either a number or the "?" */ if (g_str_has_suffix (str,"?")) { isnumbered = 0; /* There must not be any character between the "?" and the searchtext */ if (strlen(str) != len+1) return AUTONUMBER_IGNORE; } else { if (!isdigit( (int) (str[len]) )) /* has at least one digit */ return AUTONUMBER_IGNORE; for (i=len+1; str[i]; i++) /* and only digits */ if (!isdigit( (int) (str[i]) )) return AUTONUMBER_IGNORE; } /* we have six cases, 3 from focus multiplied by 2 selection cases */ if ((autotext->root_page || autotext->scope_number == SCOPE_HIERARCHY) && (o_current->selected || autotext->scope_number == SCOPE_HIERARCHY || autotext->scope_number == SCOPE_PAGE) && (!isnumbered || (autotext->scope_overwrite))) return AUTONUMBER_RENUMBER; if (isnumbered && !(autotext->scope_skip == SCOPE_SELECTED && !(o_current->selected) && autotext->root_page)) { sscanf(&(str[len])," %d", number); return AUTONUMBER_RESPECT; /* numbered objects which we don't renumber */ } else return AUTONUMBER_IGNORE; /* unnumbered objects outside the focus */ }
/*! \todo Finish function documentation!!! * \brief Change slot of selected component * \par Function Description * */ void o_slot_start (GSCHEM_TOPLEVEL *w_current, OBJECT *object) { OBJECT *slot_text_object; char *default_slot_value; char *slot_value; /* single object for now */ if (object->type == OBJ_COMPLEX) { /* first see if slot attribute already exists outside * complex */ slot_value = o_attrib_search_slot(object, &slot_text_object); if (slot_value) { #if DEBUG printf("slot=%s\n", slot_value); printf("text string : %s\n", slot_text_object->text->string); #endif slot_edit_dialog(w_current, o_text_get_string (w_current->toplevel, slot_text_object)); g_free(slot_value); } else { /* we didn't find an attached slot=? attribute */ /* See if there is a default value */ default_slot_value = o_attrib_search_default_slot(object); if (default_slot_value) { slot_value = g_strdup_printf ("slot=%s", default_slot_value); } else { /* no default, make something up? */ /* for now.. this is an error condition */ slot_value = g_strdup ("slot=1"); } #if DEBUG printf("slot value: %s\n", slot_value); #endif slot_edit_dialog(w_current, slot_value); g_free(slot_value); g_free(default_slot_value); } } }
/*! \brief Show the hide text widget */ void hide_text_dialog (GschemToplevel *w_current) { OBJECT *object; g_return_if_fail (w_current != NULL); g_return_if_fail (w_current->toplevel != NULL); object = o_select_return_first_object (w_current); if ((object != NULL) && (object->type == OBJ_TEXT)) { gschem_show_hide_text_widget_set_text_string( GSCHEM_SHOW_HIDE_TEXT_WIDGET (w_current->hide_text_widget), o_text_get_string (w_current->toplevel, object) ); } gtk_widget_show (GTK_WIDGET (w_current->hide_text_widget)); gtk_widget_grab_focus (gschem_show_hide_text_widget_get_entry (GSCHEM_SHOW_HIDE_TEXT_WIDGET (w_current->hide_text_widget))); gtk_editable_select_region (GTK_EDITABLE (gschem_show_hide_text_widget_get_entry (GSCHEM_SHOW_HIDE_TEXT_WIDGET (w_current->hide_text_widget))), 0, -1); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * * \todo Only descends into the first source schematic * */ int o_edit_find_text (GSCHEM_TOPLEVEL *w_current, const GList *o_list, char *stext, int descend, int skip) { TOPLEVEL *toplevel = w_current->toplevel; char *attrib = NULL; int count = 0; PAGE *parent = NULL; char *current_filename = NULL; int page_control = 0; int pcount = 0; int rv; int x1, y1, x2, y2; int text_screen_height; const GList *iter; OBJECT *o_current; skiplast = skip; iter = o_list; while (iter != NULL) { o_current = (OBJECT *)iter->data; if (descend) { if (o_current->type == OBJ_COMPLEX) { parent = toplevel->page_current; attrib = o_attrib_search_attached_attribs_by_name (o_current, "source", count); /* if above is null, then look inside symbol */ if (attrib == NULL) { attrib = o_attrib_search_inherited_attribs_by_name (o_current, "source", count); /* looking_inside = TRUE; */ } if (attrib) { pcount = 0; current_filename = u_basic_breakup_string(attrib, ',', pcount); if (current_filename != NULL) { PAGE *child_page = s_hierarchy_down_schematic_single(toplevel, current_filename, parent, page_control, HIERARCHY_NORMAL_LOAD); if (child_page != NULL) { page_control = child_page->page_control; rv = o_edit_find_text (w_current, s_page_objects (child_page), stext, descend, skiplast); if (!rv) { s_page_goto( toplevel, child_page ); return 0; } } } } } } if (o_current->type == OBJ_TEXT) { const gchar *str = o_text_get_string (toplevel, o_current); /* replaced strcmp with strstr to simplify the search */ if (strstr (str,stext)) { if (!skiplast) { a_zoom(w_current, ZOOM_FULL, DONTCARE, A_PAN_DONT_REDRAW); world_get_single_object_bounds (toplevel, o_current, &x1, &y1, &x2, &y2); text_screen_height = SCREENabs (w_current, y2 - y1); /* this code will zoom/pan till the text screen height is about */ /* 50 pixels high, perhaps a future enhancement will be to make */ /* this number configurable */ while (text_screen_height < 50) { a_zoom(w_current, ZOOM_IN, DONTCARE, A_PAN_DONT_REDRAW); text_screen_height = SCREENabs (w_current, y2 - y1); } a_pan_general(w_current, o_current->text->x, o_current->text->y, 1, 0); /* Make sure the titlebar and scrollbars are up-to-date */ x_window_set_current_page(w_current, w_current->toplevel->page_current ); last_o = o_current; break; } if (last_o == o_current) { skiplast = 0; } } /* if (strstr(o_current->text->string,stext)) */ } /* if (o_current->type == OBJ_TEXT) */ iter = g_list_next (iter); if (iter == NULL) { return 1; } } return (iter == NULL); }
/*! \brief Handles all the options of the autonumber text dialog * \par Function Description * This function is the master of all autonumber code. It receives the options of * the the autonumber text dialog in an <B>AUTONUMBER_TEXT</B> structure. * First it collects all pages of a hierarchical schematic. * Second it gets all matching text elements for the searchtext. * Then it renumbers all text elements of all schematic pages. The renumbering * follows the rules of the parameters given in the autonumber text dialog. */ void autonumber_text_autonumber(AUTONUMBER_TEXT *autotext) { GList *pages; GList *searchtext_list=NULL; GList *text_item, *obj_item, *page_item; OBJECT *o_current; GschemToplevel *w_current; gchar *searchtext; gchar *scope_text; gchar *new_searchtext; gint i, number, slot; GList *o_list = NULL; const GList *iter; w_current = autotext->w_current; autotext->current_searchtext = NULL; autotext->root_page = 1; autotext->used_numbers = NULL; autotext->free_slots = NULL; autotext->used_slots = NULL; scope_text = g_list_first(autotext->scope_text)->data; /* Step1: get all pages of the hierarchy */ pages = s_hierarchy_traversepages (w_current->toplevel, w_current->toplevel->page_current, HIERARCHY_NODUPS); /* g_list_foreach(pages, (GFunc) s_hierarchy_print_page, NULL); */ /* Step2: if searchtext has an asterisk at the end we have to find all matching searchtextes. Example: "refdes=*" will match each text that starts with "refdes=" and has a trailing "?" or a trailing number if the "all"-option is set. We get a list of possible prefixes: refdes=R, refdes=C. If there is only one search pattern, it becomes a single item in the searchtext list */ if (strlen(scope_text) == 0) { s_log_message(_("No searchstring given in autonumber text.\n")); return; /* error */ } else if (g_str_has_suffix(scope_text,"?") == TRUE) { /* single searchtext, strip of the "?" */ searchtext = g_strndup(scope_text, strlen(scope_text)-1); searchtext_list=g_list_append (searchtext_list, searchtext); } else if (g_str_has_suffix(scope_text,"*") == TRUE) { /* strip of the "*" */ searchtext = g_strndup(scope_text, strlen(scope_text)-1); /* collect all the possible searchtexts in all pages of the hierarchy */ for (page_item = pages; page_item != NULL; page_item = g_list_next(page_item)) { s_page_goto(w_current->toplevel, page_item->data); gschem_toplevel_page_changed (w_current); /* iterate over all objects an look for matching searchtext's */ for (iter = s_page_objects (w_current->toplevel->page_current); iter != NULL; iter = g_list_next (iter)) { o_current = iter->data; if (o_current->type == OBJ_TEXT) { if (autotext->scope_number == SCOPE_HIERARCHY || autotext->scope_number == SCOPE_PAGE || ((autotext->scope_number == SCOPE_SELECTED) && (o_current->selected))) { const gchar *str = o_text_get_string (w_current->toplevel, o_current); if (g_str_has_prefix (str, searchtext)) { /* the beginnig of the current text matches with the searchtext now */ /* strip of the trailing [0-9?] chars and add it too the searchtext */ for (i = strlen (str)-1; (i >= strlen(searchtext)) && (str[i] == '?' || isdigit( (int) (str[i]) )); i--) ; /* void */ new_searchtext = g_strndup (str, i+1); if (g_list_find_custom(searchtext_list, new_searchtext, (GCompareFunc) strcmp) == NULL ) { searchtext_list = g_list_append(searchtext_list, new_searchtext); } else { g_free(new_searchtext); } } } } } if (autotext->scope_number == SCOPE_SELECTED || autotext->scope_number == SCOPE_PAGE) break; /* search only in the first page */ } g_free(searchtext); } else { s_log_message(_("No '*' or '?' given at the end of the autonumber text.\n")); return; } /* Step3: iterate over the search items in the list */ for (text_item=searchtext_list; text_item !=NULL; text_item=g_list_next(text_item)) { autotext->current_searchtext = text_item->data; /* printf("autonumber_text_autonumber: searchtext %s\n", autotext->current_searchtext); */ /* decide whether to renumber page by page or get a global used-list */ if (autotext->scope_skip == SCOPE_HIERARCHY) { /* whole hierarchy database */ /* renumbering all means that no db is required */ if (!(autotext->scope_number == SCOPE_HIERARCHY && autotext->scope_overwrite)) { for (page_item = pages; page_item != NULL; page_item = g_list_next(page_item)) { autotext->root_page = (pages->data == page_item->data); s_page_goto(w_current->toplevel, page_item->data); gschem_toplevel_page_changed (w_current); autonumber_get_used(w_current, autotext); } } } /* renumber the elements */ for (page_item = pages; page_item != NULL; page_item = g_list_next(page_item)) { s_page_goto(w_current->toplevel, page_item->data); gschem_toplevel_page_changed (w_current); autotext->root_page = (pages->data == page_item->data); /* build a page database if we're numbering pagebypage or selection only*/ if (autotext->scope_skip == SCOPE_PAGE || autotext->scope_skip == SCOPE_SELECTED) { autonumber_get_used(w_current, autotext); } /* RENUMBER CODE FOR ONE PAGE AND ONE SEARCHTEXT*/ /* 1. get objects to renumber */ for (iter = s_page_objects (w_current->toplevel->page_current); iter != NULL; iter = g_list_next (iter)) { o_current = iter->data; if (autonumber_match(autotext, o_current, &number) == AUTONUMBER_RENUMBER) { /* put number into the used list */ o_list = g_list_append(o_list, o_current); } } /* 2. sort object list */ switch (autotext->order) { case AUTONUMBER_SORT_YX: o_list=g_list_sort(o_list, autonumber_sort_yx); break; case AUTONUMBER_SORT_YX_REV: o_list=g_list_sort(o_list, autonumber_sort_yx_rev); break; case AUTONUMBER_SORT_XY: o_list=g_list_sort(o_list, autonumber_sort_xy); break; case AUTONUMBER_SORT_XY_REV: o_list=g_list_sort(o_list, autonumber_sort_xy_rev); break; case AUTONUMBER_SORT_DIAGONAL: o_list=g_list_sort(o_list, autonumber_sort_diagonal); break; default: ; /* unsorted file order */ } /* 3. renumber/reslot the objects */ for(obj_item=o_list; obj_item != NULL; obj_item=g_list_next(obj_item)) { o_current= obj_item->data; if(autotext->removenum) { autonumber_remove_number(autotext, o_current); } else { /* get valid numbers from the database */ autonumber_get_new_numbers(autotext, o_current, &number, &slot); /* and apply it. TODO: join these two functions */ autonumber_apply_new_text(autotext, o_current, number, slot); } } g_list_free(o_list); o_list = NULL; /* destroy the page database */ if (autotext->scope_skip == SCOPE_PAGE || autotext->scope_skip == SCOPE_SELECTED) autonumber_clear_database(autotext); if (autotext->scope_number == SCOPE_SELECTED || autotext->scope_number == SCOPE_PAGE) break; /* only renumber the parent page (the first page) */ } autonumber_clear_database(autotext); /* cleanup */ } /* cleanup and redraw all*/ g_list_foreach(searchtext_list, (GFunc) g_free, NULL); g_list_free(searchtext_list); s_page_goto(w_current->toplevel, pages->data); /* go back to the root page */ gschem_toplevel_page_changed (w_current); gschem_page_view_invalidate_all (gschem_toplevel_get_current_page_view (w_current)); g_list_free(pages); o_undo_savestate_old(w_current, UNDO_ALL); }
/*! \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); } } } }