Beispiel #1
0
/*! \brief Recalculate position of a list (GList) of objects.
 *  \par Function Description
 *  This function will take a list (GList) of objects and recalculate their
 *  positions on the screen.
 *
 *  \param [in]     toplevel    The TOPLEVEL object.
 *  \param [in,out] object_glist  OBJECT list to recalculate.
 *
 */
void
o_recalc_object_glist(TOPLEVEL *toplevel, GList *object_glist)
{
  GList *list = object_glist;
  OBJECT *o_current;

  while (list != NULL) {
    o_current = (OBJECT *) list->data;
    o_recalc_single_object(toplevel, o_current);
   list = g_list_next(list);
  }
}
Beispiel #2
0
/*! \brief Set an #OBJECT's line options.
 *  \par Function Description
 *  This function allows a line's end, type, width, length and space to be set.
 *  See #OBJECT_END and #OBJECT_TYPE for information on valid
 *  object end and type values.
 *
 *  \param [in]     toplevel  The TOPLEVEL object.
 *  \param [in,out] o_current  OBJECT to set line options on.
 *  \param [in]     end        An OBJECT_END.
 *  \param [in]     type       An OBJECT_TYPE.
 *  \param [in]     width      Line width.
 *  \param [in]     length     Line length.
 *  \param [in]     space      Spacing between dashes/dots. Cannot be negative.
 *
 *  \todo Make space an unsigned int and check for a max value instead.
 *        If a max value is not required, then it would simplify the code.
 */
void o_set_line_options(TOPLEVEL *toplevel, OBJECT *o_current,
			OBJECT_END end, OBJECT_TYPE type,
			int width, int length, int space) 
{
  if(o_current == NULL) {
    return;
  }

  /* do some error checking / correcting */
  switch(type) {
    case(TYPE_DOTTED):
    if (space < 1) {
      space = 100;
      s_log_message (_("Invalid space specified, setting to 100\n"));
    }
    break;
    case(TYPE_DASHED):
    case(TYPE_CENTER):
    case(TYPE_PHANTOM):
    if (length < 1) {
      length = 100;
      s_log_message (_("Invalid length specified, setting to 100\n"));
    }
    if (space < 1) {
      space = 100;
      s_log_message (_("Invalid space specified, setting to 100\n"));
    }
    break;
    default:
    
    break;
  }
  
  o_emit_pre_change_notify (toplevel, o_current);

  o_current->line_width = width;
  o_current->line_end   = end;
  o_current->line_type  = type;

  o_current->line_length = length;
  o_current->line_space  = space;

  /* Recalculate the object's bounding box */
  o_recalc_single_object( toplevel, o_current );
  o_emit_change_notify (toplevel, o_current);

}
Beispiel #3
0
/*! \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;
}
Beispiel #4
0
/*! \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);
  }
}
Beispiel #5
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 */
int o_net_add_busrippers(GSCHEM_TOPLEVEL *w_current, OBJECT *net_obj,
                         GList *prev_conn_objects)

{
  TOPLEVEL *toplevel = w_current->toplevel;
  OBJECT *new_obj;
  int color;
  GList *cl_current = NULL;
  OBJECT *bus_object = NULL;
  CONN *found_conn = NULL;
  int done;
  int otherone;
  BUS_RIPPER rippers[2];
  int ripper_count = 0;
  int i;
  double length;
  int sign;
  double distance1, distance2;
  int first, second;
  int made_changes = FALSE;
  const int ripper_size = w_current->bus_ripper_size;
  int complex_angle = 0;
  const CLibSymbol *rippersym = NULL;
  
  length = o_line_length(net_obj);

  if (!prev_conn_objects) {
    return(FALSE);
  }
  
  if (length <= ripper_size) {
    return(FALSE);
  }

  if (toplevel->override_net_color == -1) {
    color = NET_COLOR;
  } else {
    color = toplevel->override_net_color;
  }

  
  /* check for a bus connection and draw rippers if so */
  cl_current = prev_conn_objects;
  while (cl_current != NULL) {
    
    bus_object = (OBJECT *) cl_current->data;
    if (bus_object && bus_object->type == OBJ_BUS) {
      /* yes, using the net routine is okay */
      int bus_orientation = o_net_orientation(bus_object);
      int net_orientation = o_net_orientation(net_obj);

      /* find the CONN structure which is associated with this object */
      GList *cl_current2 = net_obj->conn_list;
      done = FALSE;
      while (cl_current2 != NULL && !done) {
	CONN *tmp_conn = (CONN *) cl_current2->data;

	if (tmp_conn && tmp_conn->other_object &&
	    tmp_conn->other_object == bus_object) {

	  found_conn = tmp_conn;
	  done = TRUE;
	}

	cl_current2 = g_list_next(cl_current2);
      }

      if (!found_conn) {
        return(FALSE);
      }
      
      otherone = !found_conn->whichone;
      
      /* now deal with the found connection */
      if (bus_orientation == HORIZONTAL && net_orientation == VERTICAL) {
	/* printf("found horiz bus %s %d!\n", bus_object->name, 
           found_conn->whichone);*/

        sign = bus_object->bus_ripper_direction;
        if (!sign) {
          if (bus_object->line->x[0] < bus_object->line->x[1]) {
            first = 0;
            second = 1;
          } else {
            first = 1;
            second = 0;
          }
              
          distance1 = abs(bus_object->line->x[first] -
                          net_obj->line->x[found_conn->whichone]);
          distance2 = abs(bus_object->line->x[second] -
                          net_obj->line->x[found_conn->whichone]);
          
          if (distance1 <= distance2) {
            sign = 1;
          } else {
            sign = -1;
          }
          bus_object->bus_ripper_direction = sign;
        }
        /* printf("hor sign: %d\n", sign); */

        if (net_obj->line->y[otherone] < bus_object->line->y[0]) {
          /* new net is below bus */
          /*printf("below\n");*/

          if (ripper_count >= 2) {
            /* try to exit gracefully */
            fprintf(stderr, _("Tried to add more than two bus rippers. Internal gschem error.\n"));
            made_changes = FALSE;
            break;
          }

          if (w_current->bus_ripper_rotation == NON_SYMMETRIC) {
            /* non-symmetric */
            if (sign == 1) {
              complex_angle = 0;
            } else {
              complex_angle = 90;
            }
          } else {
            /* symmetric */
            complex_angle = 0;
          }

          net_obj->line->y[found_conn->whichone] -= ripper_size;
          o_recalc_single_object(toplevel, net_obj);
          rippers[ripper_count].x[0] = 
            net_obj->line->x[found_conn->whichone];
          rippers[ripper_count].y[0] =
            net_obj->line->y[found_conn->whichone];
          rippers[ripper_count].x[1] =
            net_obj->line->x[found_conn->whichone] + sign*ripper_size;       
          rippers[ripper_count].y[1] =
            net_obj->line->y[found_conn->whichone] + ripper_size;
          ripper_count++;
          /* printf("done\n"); */
          made_changes++;
          
        } else {
          /* new net is above bus */
          /* printf("above\n"); */

          if (ripper_count >= 2) {
            /* try to exit gracefully */
            fprintf(stderr, _("Tried to add more than two bus rippers. Internal gschem error.\n"));
            made_changes = FALSE;
            break;
          }

          if (w_current->bus_ripper_rotation == NON_SYMMETRIC) {
            /* non-symmetric */
            if (sign == 1) {
              complex_angle = 270;
            } else {
              complex_angle = 180;
            }
          } else {
            /* symmetric */
            complex_angle = 180;
          }
          
          net_obj->line->y[found_conn->whichone] += ripper_size;
          o_recalc_single_object(toplevel, net_obj);
          rippers[ripper_count].x[0] = 
            net_obj->line->x[found_conn->whichone];
          rippers[ripper_count].y[0] =
            net_obj->line->y[found_conn->whichone];
          rippers[ripper_count].x[1] =
            net_obj->line->x[found_conn->whichone] + sign*ripper_size;      
          rippers[ripper_count].y[1] =
            net_obj->line->y[found_conn->whichone] - ripper_size;
            ripper_count++;
            
            /* printf("done\n"); */
          made_changes++;
        }
        
        
      } else if (bus_orientation == VERTICAL &&
		 net_orientation == HORIZONTAL) {

	/* printf("found vert bus %s %d!\n", bus_object->name,
           found_conn->whichone); */

        sign = bus_object->bus_ripper_direction;
        if (!sign) {
          if (bus_object->line->y[0] < bus_object->line->y[1]) {
            first = 0;
            second = 1;
          } else {
            first = 1;
            second = 0;
          }

          distance1 = abs(bus_object->line->y[first] -
                          net_obj->line->y[found_conn->whichone]);
          distance2 = abs(bus_object->line->y[second] -
                          net_obj->line->y[found_conn->whichone]);
          
          if (distance1 <= distance2) {
            sign = 1;
          } else {
            sign = -1;
          }
          bus_object->bus_ripper_direction = sign;
        } 
        /* printf("ver sign: %d\n", sign); */

        
        if (net_obj->line->x[otherone] < bus_object->line->x[0]) {
          /* new net is to the left of the bus */
          /* printf("left\n"); */
          
          if (ripper_count >= 2) {
            /* try to exit gracefully */
            fprintf(stderr, _("Tried to add more than two bus rippers. Internal gschem error.\n"));
            made_changes = FALSE;
            break;
          }

          if (w_current->bus_ripper_rotation == NON_SYMMETRIC) {
            /* non-symmetric */
            if (sign == 1) {
              complex_angle = 0;
            } else {
              complex_angle = 270;
            }
          } else {
            /* symmetric */
            complex_angle = 270;
          }

          net_obj->line->x[found_conn->whichone] -= ripper_size;
          o_recalc_single_object(toplevel, net_obj);
          rippers[ripper_count].x[0] = 
            net_obj->line->x[found_conn->whichone];
          rippers[ripper_count].y[0] =
            net_obj->line->y[found_conn->whichone];
          rippers[ripper_count].x[1] =
            net_obj->line->x[found_conn->whichone] + ripper_size;
          rippers[ripper_count].y[1] =
            net_obj->line->y[found_conn->whichone] + sign*ripper_size;
          ripper_count++;
                    
          made_changes++;
        } else {
          /* new net is to the right of the bus */
          /* printf("right\n"); */

          if (ripper_count >= 2) {
            /* try to exit gracefully */
            fprintf(stderr, _("Tried to add more than two bus rippers. Internal gschem error.\n"));
            made_changes = FALSE;
            break;
          }

          if (w_current->bus_ripper_rotation == NON_SYMMETRIC) {
            /* non-symmetric */
            if (sign == 1) {
              complex_angle = 90;
            } else {
              complex_angle = 180;
            }
          } else {
            /* symmetric */
            complex_angle = 90;
          }

          net_obj->line->x[found_conn->whichone] += ripper_size;
          o_recalc_single_object(toplevel, net_obj);
          rippers[ripper_count].x[0] = 
            net_obj->line->x[found_conn->whichone];
          rippers[ripper_count].y[0] =
            net_obj->line->y[found_conn->whichone];
          rippers[ripper_count].x[1] =
            net_obj->line->x[found_conn->whichone] - ripper_size;
          rippers[ripper_count].y[1] =
            net_obj->line->y[found_conn->whichone] + sign*ripper_size;
          ripper_count++;

          made_changes++;
        }
      }
    }


    cl_current = g_list_next(cl_current);
  }
 
  if (made_changes) {
    s_conn_remove_object (toplevel, net_obj);

    if (w_current->bus_ripper_type == COMP_BUS_RIPPER) {
      GList *symlist = 
	s_clib_search (toplevel->bus_ripper_symname, CLIB_EXACT);
      if (symlist != NULL) {
        rippersym = (CLibSymbol *) symlist->data;
      }
      g_list_free (symlist);
    }
    
    for (i = 0; i < ripper_count; i++) {
      if (w_current->bus_ripper_type == NET_BUS_RIPPER) {
        new_obj = o_net_new(toplevel, OBJ_NET, color,
                  rippers[i].x[0], rippers[i].y[0],
                  rippers[i].x[1], rippers[i].y[1]);
        s_page_append (toplevel->page_current, new_obj);
      } else {

        if (rippersym != NULL) {
          new_obj = o_complex_new (toplevel, OBJ_COMPLEX, DEFAULT_COLOR,
                                   rippers[i].x[0], rippers[i].y[0],
                                   complex_angle, 0,
                                   rippersym,
                                   toplevel->bus_ripper_symname, 1);
          s_page_append_list (toplevel->page_current,
                              o_complex_promote_attribs (toplevel, new_obj));
          s_page_append (toplevel->page_current, new_obj);

          o_invalidate (w_current, new_obj);
        } else {
          s_log_message(_("Bus ripper symbol [%s] was not found in any component library\n"),
                        toplevel->bus_ripper_symname);
        }
      }
    }
    
    s_conn_update_object (toplevel, net_obj);
    return(TRUE);
  }

  return(FALSE);
}