示例#1
0
/*! \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);
}
示例#2
0
文件: o_misc.c 项目: vzh/geda-gaf
/*! \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);
}
示例#3
0
/* 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;
}
示例#4
0
文件: o_text.c 项目: dmay31/geda-gaf
/*! \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);
}
示例#5
0
/*! \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? */
}
示例#6
0
/*! \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 */
}
示例#7
0
/*! \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);
}
示例#9
0
/*! \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);
}
示例#10
0
/*! \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);
}
示例#11
0
/*! \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);
            }
        }
    }
}