Пример #1
0
/*! \brief Unembed a picture, reloading the image from disk
 *
 *  \par Function Description
 *  This function re-reads the image file associated with the picture, and
 *  discards the embeded copy of the file.
 *
 *  \param [in]     toplevel     The TOPLEVEL object.
 *  \param [in]     object       The picture OBJECT to unembed
 */
void o_picture_unembed (TOPLEVEL *toplevel, OBJECT *object)
{
  GError *err = NULL;
  GdkPixbuf *pixbuf;
  gchar *filename;

  pixbuf = gdk_pixbuf_new_from_file (object->picture->filename, &err);
  if (err != NULL) {
    s_log_message (_("Failed to load image from file [%s]: %s\n"),
                   object->picture->filename, err->message);
    g_error_free (err);
    return;
  }

  /* Change to the new pixbuf loaded from the file. */
  if (object->picture->original_picture != NULL)
    g_object_unref(object->picture->original_picture);

  object->picture->original_picture = pixbuf;

  g_free (object->picture->file_content);
  object->picture->file_content = NULL;
  object->picture->file_length = 0;
  object->picture->embedded = 0;

  filename = g_path_get_basename(object->picture->filename);
  s_log_message (_("Picture [%s] has been unembedded\n"), filename);
  g_free(filename);
}
Пример #2
0
/*! \brief Add symbol-generating Scheme procedures to the library.
 *  \par Function Description
 *  Adds a source to the library based on Scheme procedures.  See page
 *  \ref libscms for more information. Two procedures are required: \a
 *  listfunc must return a Scheme list of symbol names, and \a getfunc
 *  must return a string containing symbol data when passed a symbol
 *  name.
 *
 *  \param listfunc A Scheme function returning a list of symbols.
 *  \param getfunc  A Scheme function returning symbol data.
 *  \param name     A descriptive name for the component source.
 *
 *  \return         The new CLibSource.
 */
const CLibSource *s_clib_add_scm (SCM listfunc, SCM getfunc, const gchar *name)
{
  CLibSource *source;
  gchar *realname;

  if (name == NULL) {
    s_log_message (_("Cannot add library: name not specified."));
    return NULL;
  }

  realname = uniquify_source_name (name);

  if (scm_is_false (scm_procedure_p (listfunc))
      && scm_is_false (scm_procedure_p (getfunc))) {
    s_log_message (_("Cannot add Scheme-library [%1$s]: callbacks must be closures."),
                   realname);
    return NULL;
  }

  source = g_new0 (CLibSource, 1);
  source->type = CLIB_SCM;
  source->name = realname;
  source->list_fn = scm_gc_protect_object (listfunc);
  source->get_fn = scm_gc_protect_object (getfunc);

  refresh_scm (source);

  clib_sources = g_list_prepend (clib_sources, source);

  return source;
}
Пример #3
0
/*! \brief read a net object from a char buffer
 *  \par Function Description
 *  This function reads a net object from the buffer \a buf.
 *  If the netobject was read successfully, a new net object is
 *  allocated and appended to the \a object_list.
 *
 *  \param [in] toplevel     The TOPLEVEL object
 *  \param [in] buf          a text buffer (usually a line of a schematic file)
 *  \param [in] release_ver  The release number gEDA
 *  \param [in] fileformat_ver a integer value of the file format
 *  \return The object list, or NULL on error.
 *
 */
OBJECT *o_net_read (TOPLEVEL *toplevel, const char buf[],
                    unsigned int release_ver, unsigned int fileformat_ver, GError **err)
{
  OBJECT *new_obj;
  char type;
  int x1, y1;
  int x2, y2;
  int color;

  if (sscanf (buf, "%c %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color) != 6) {
        g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse net object"));
    return NULL;
  }

  if (x1 == x2 && y1 == y2) {
    s_log_message (_("Found a zero length net [ %c %d %d %d %d %d ]\n"),
                   type, x1, y1, x2, y2, color);
  }


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

  if (color < 0 || color > MAX_COLORS) {
    s_log_message (_("Found an invalid color [ %s ]\n"), buf);
    s_log_message (_("Setting color to default color\n"));
    color = DEFAULT_COLOR;
  }

  new_obj = o_net_new (toplevel, type, color, x1, y1, x2, y2);

  return new_obj;
}
Пример #4
0
/*! \brief Add symbol-generating commands to the library
 *  \par Function Description
 *  Adds a set of commands which can generate symbols to the
 *  library. \a list_cmd and \a get_cmd should be strings consisting
 *  of an executable name followed by any arguments required.
 *  Executables are resolved using the current PATH.  See page \ref
 *  libcmds for more information on library commands.
 *
 *  \param list_cmd The executable & arguments used to list available
 *                   symbols.
 *  \param get_cmd  The executable & arguments used to retrieve symbol
 *                   data.
 *  \param name      A descriptive name for the component source.
 *  \return The CLibSource associated with the component source.
 */
const CLibSource *s_clib_add_command (const gchar *list_cmd,
                                      const gchar *get_cmd,
				      const gchar *name)
{
  CLibSource *source;
  gchar *realname;

  if (name == NULL) {
    s_log_message (_("Cannot add library: name not specified."));
    return NULL;
  }

  realname = uniquify_source_name (name);

  if (list_cmd == NULL || get_cmd == NULL) {
    s_log_message (_("Cannot add library [%1$s]: both 'list' and "
                     "'get' commands must be specified."),
		   realname);
  }

  source = g_new0 (CLibSource, 1);
  source->type = CLIB_CMD;
  source->name = realname;

  source->list_cmd = g_strdup (list_cmd);
  source->get_cmd = g_strdup (get_cmd);

  refresh_command (source);

  /* Sources added later get sacnned earlier */
  clib_sources = g_list_prepend (clib_sources, source);

  return source;
}
Пример #5
0
static void
g_rc_parse__process_error (GError **err, const gchar *pname)
{
  char *pbase;

  /* Take no chances; if err was not set for some reason, bail out. */
  if (*err == NULL) {
    const gchar *msgl =
      _("ERROR: An unknown error occurred while parsing configuration files.");
    s_log_message ("%s\n", msgl);
    fprintf(stderr, "%s\n", msgl);

  } else {
    /* Config files are allowed to be missing or skipped; check for
     * this. */
    if (g_error_matches (*err, G_FILE_ERROR, G_FILE_ERROR_NOENT) ||
        g_error_matches (*err, EDA_ERROR, EDA_ERROR_RC_TWICE)) {
      return;
    }

    s_log_message (_("ERROR: %s\n"), (*err)->message);
    fprintf (stderr, _("ERROR: %s\n"), (*err)->message);
  }

  /* g_path_get_basename() allocates memory, but we don't care
   * because we're about to exit. */
  pbase = g_path_get_basename (pname);
  fprintf (stderr, _("ERROR: The %s log may contain more information.\n"),
           pbase);
  exit (1);
}
Пример #6
0
/*! \brief Saves all the pages of a TOPLEVEL object.
 *  \par Function Description
 *  Saves all the pages in the <B>toplevel</B> parameter.
 *
 *  \param [in] toplevel  The TOPLEVEL to save pages from.
 *  \return The number of failed tries to save a page.
 */
gint s_page_save_all (TOPLEVEL *toplevel)
{
  const GList *iter;
  PAGE *p_current;
  gint status = 0;

  for ( iter = geda_list_get_glist( toplevel->pages );
        iter != NULL;
        iter = g_list_next( iter ) ) {

    p_current = (PAGE *)iter->data;

    if (f_save (toplevel, p_current,
                p_current->page_filename, NULL)) {
      s_log_message (_("Saved [%s]\n"),
                     p_current->page_filename);
      /* reset the CHANGED flag of p_current */
      p_current->CHANGED = 0;

    } else {
      s_log_message (_("Could NOT save [%s]\n"),
                     p_current->page_filename);
      /* increase the error counter */
      status++;
    }

  }

  return status;
}
Пример #7
0
/*! \brief
 *  \par Function Description
 *  This function reads a formatted text buffer describing an arc
 *  in the gEDA file format and initializes the corresponding object.
 *
 *  Depending on the version of the file format the data extraction is
 *  performed differently : currently pre-20000704 and 20000704 on one
 *  hand and post-20000704 file format version on the other hand are supported.
 *  The version is specified in string pointed by <B>fileformat_ver</B>.
 *
 *  To get information on the various file formats have a
 *  look to the fileformats.html document.
 *  
 *  The object is initialized with the functions #o_set_line_options() and #o_set_fill_options().
 *  The second one is only used to put initialize unused values for an arc as an arc can not be filled.
 * 
 *  The arc is allocated initialized with the function #o_arc_new().
 * 
 *  A negative or null radius is not allowed.
 *
 *  \param [in] toplevel    The TOPLEVEL object.
 *  \param [in] buf
 *  \param [in] release_ver
 *  \param [in] fileformat_ver
 *  \return
 */
OBJECT *o_arc_read (TOPLEVEL *toplevel, char buf[],
		   unsigned int release_ver, unsigned int fileformat_ver)
{
  OBJECT *new_obj;
  char type; 
  int x1, y1;
  int radius;
  int start_angle, end_angle;
  int color;
  int arc_width, arc_length, arc_space;
  int arc_type;
  int arc_end;

  /*! \note
   *  Depending on the version of the file format used to describe this arc,
   *  the buffer is parsed differently. The unknown parameters of the less
   *  restrictive - the oldest - file format are set to common values
   */
  if(release_ver <= VERSION_20000704) {
    sscanf(buf, "%c %d %d %d %d %d %d", &type,
           &x1, &y1, &radius, &start_angle, &end_angle, &color);

    arc_width = 0;
    arc_end   = END_NONE;
    arc_type  = TYPE_SOLID;
    arc_space = -1;
    arc_length= -1;
  } else {
    sscanf(buf, "%c %d %d %d %d %d %d %d %d %d %d %d", &type,
           &x1, &y1, &radius, &start_angle, &end_angle, &color,
           &arc_width, &arc_end, &arc_type, &arc_length, &arc_space);

  }

  /* Error check */
  if (radius <= 0) {
    s_log_message (_("Found a zero radius arc [ %c %d, %d, %d, %d, %d, %d ]\n"),
                   type, x1, y1, radius, start_angle, end_angle, color);
  }
	
  if (color < 0 || color > MAX_COLORS) {
    s_log_message(_("Found an invalid color [ %s ]\n"), buf);
    s_log_message(_("Setting color to default color\n"));
    color = DEFAULT_COLOR;
  }

  /* Allocation and initialization */
  new_obj = o_arc_new(toplevel, OBJ_ARC, color,
                      x1, y1, radius, start_angle, end_angle);
  o_set_line_options(toplevel, new_obj,
                     arc_end, arc_type, arc_width, arc_length,
                     arc_space);
  o_set_fill_options(toplevel, new_obj,
                     FILLING_HOLLOW, -1, -1, -1,
                     -1, -1);

  return new_obj;
}
Пример #8
0
/*! \brief Re-poll a scheme procedure for symbols.
 *  \par Function Description
 *  Calls a Scheme procedure to obtain a list of available symbols,
 *  and updates the source with the new list
 *
 *  Private function used only in s_clib.c.
 */
static void refresh_scm (CLibSource *source)
{
  SCM symlist;
  SCM symname;
  CLibSymbol *symbol;
  char *tmp;

  g_return_if_fail (source != NULL);
  g_return_if_fail (source->type == CLIB_SCM);

  /* Clear the current symbol list */
  g_list_foreach (source->symbols, (GFunc) free_symbol, NULL);
  g_list_free (source->symbols);
  source->symbols = NULL;

  symlist = scm_call_0 (source->list_fn);

  if (scm_is_false (scm_list_p (symlist))) {
    s_log_message (_("Failed to scan library [%1$s]: Scheme function returned non-list."),
		   source->name);
    return;
  }

  while (!scm_is_null (symlist)) {
    symname = SCM_CAR (symlist);
    if (!scm_is_string (symname)) {
      s_log_message (_("Non-string symbol name while scanning library [%1$s]"),
		     source->name);
    } else {
      symbol = g_new0 (CLibSymbol, 1);
      symbol->source = source;

      /* Need to make sure that the correct free() function is called
       * on strings allocated by Guile. */
      tmp = scm_to_utf8_string (symname);
      symbol->name = g_strdup(tmp);
      free (tmp);

      /* Prepend because it's faster and it doesn't matter what order we
       * add them. */
      source->symbols = g_list_prepend (source->symbols, symbol);
    }

    symlist = SCM_CDR (symlist);
  }

  /* Now sort the list of symbols by name. */
  source->symbols = g_list_sort (source->symbols,
				 (GCompareFunc) compare_symbol_name);

  s_clib_flush_search_cache();
  s_clib_flush_symbol_cache();
}
Пример #9
0
/*! \brief Use gschemdoc to open a browser to a specific wiki page
 *
 * \param [in] wikiname the name of the wiki page
 *
 * \par Function Description
 * Invokes gschemdoc with its -w switch to open a browser to the wiki
 * page specified by wikiname.  If wikiname is empty or not a string, 
 * will browse to the main wiki page.
 */
SCM g_funcs_browse_wiki(SCM wikiname)
{
  char *wikistr;
  int pid;

  /* Extract wiki name string from Scheme value structure.
   * If not a string, use the empty string */
  if (scm_is_string (wikiname)) {
    wikistr = scm_to_utf8_string(wikiname);
  } else {
    wikistr = "";
  }

  #ifndef __MINGW32__

  pid = fork();

  if (pid < 0) {
    /* Fork failed. Still in parent process, so can use the log
     * window */
    if (scm_is_string (wikiname))
      free(wikistr);
    s_log_message(_("Could not fork\n"));
    return SCM_BOOL_F;
  } else if (pid > 0) {
    /* Parent process, we're finished here */
    if (scm_is_string (wikiname))
      free(wikistr);
    return SCM_BOOL_T;
  }
  
  /* begin daughter process stuff */
  
  /* assume gschemdoc is part of path */
  char *gschemdoc = "gschemdoc";
  char *wikiarg = "-w";
  
  execlp(gschemdoc, gschemdoc, wikiarg, wikistr, NULL);

  /* if we return, then nothing happened */
  fprintf(stderr, _("Could not invoke %s\n"), gschemdoc);
  _exit(0);

  /* end daughter process stuff */

#else /* __MINGW32__ */
  s_log_message(_("Documentation commands not supported under MinGW.\n"));
  return SCM_BOOL_F;
#endif /* __MINGW32__ */
}
Пример #10
0
void
s_symstruct_print(SYMCHECK *s_current)
{
  GList *list;
  char *msg;

  if (verbose_mode > 2) {
    list = s_current->info_messages;
    while (list != NULL) {
      msg = (char *) list->data;     
      /* printf("found info: %s\n", msg); */
      if (msg) { 
        s_log_message(_("Info: %1$s"), msg);
        g_free(msg);
      }

      list = g_list_next(list);
    }
  }

  if (verbose_mode > 1) {
    list = s_current->warning_messages;
    while (list != NULL) {
      msg = (char *) list->data;     
     
      /* printf("found warning: %s\n", msg); */
      if (msg) { 
        s_log_message(_("Warning: %1$s"), msg);
        g_free(msg);
      }

      list = g_list_next(list);
    }
  }

  if (verbose_mode > 0) {
    list = s_current->error_messages;
    while (list != NULL) {
      msg = (char *) list->data;     
     
      /* printf("found error: %s\n", msg); */
      if (msg && verbose_mode) { 
        s_log_message(_("ERROR: %1$s"), msg);
        g_free(msg);
      }

      list = g_list_next(list);
    }
  }
}
Пример #11
0
/*! \brief read a pin object from a char buffer
 *  \par Function Description
 *  This function reads a pin object from the buffer \a buf.
 *  If the pin object was read successfully, a new pin object is
 *  allocated and appended to the \a object_list.
 *
 *  \param [in] toplevel     The TOPLEVEL object
 *  \param [in] buf          a text buffer (usually a line of a schematic file)
 *  \param [in] release_ver  The release number gEDA
 *  \param [in] fileformat_ver a integer value of the file format
 *  \return The object list, or NULL on error.
 */
OBJECT *o_pin_read (TOPLEVEL *toplevel, const char buf[],
                    unsigned int release_ver, unsigned int fileformat_ver, GError **err)
{
  OBJECT *new_obj;
  char type; 
  int x1, y1;
  int x2, y2;
  int color;
  int pin_type;
  int whichend;

  if (release_ver <= VERSION_20020825) {
    if (sscanf (buf, "%c %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color) != 6) {
      g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse pin object"));
      return NULL;
    }
    pin_type = PIN_TYPE_NET;
    whichend = -1;
  } else {
    if (sscanf (buf, "%c %d %d %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2,
		&color, &pin_type, &whichend) != 8) {
      g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse pin object"));
      return NULL;
    }
  }

  if (whichend == -1) {
    s_log_message (_("Found a pin which did not have the whichone field set.\n"
                     "Verify and correct manually.\n"));
  } else if (whichend < -1 || whichend > 1) {
    s_log_message (_("Found an invalid whichend on a pin (reseting to zero): %d\n"),
                   whichend);
    whichend = 0;
  }

  if (color < 0 || color > MAX_COLORS) {
    s_log_message (_("Found an invalid color [ %s ]\n"), buf);
    s_log_message (_("Setting color to default color\n"));
    color = DEFAULT_COLOR;
  }

  if (toplevel->override_pin_color != -1) {
    color = toplevel->override_pin_color;
  }

  new_obj = o_pin_new (toplevel, type, color, x1, y1, x2, y2,
                       pin_type, whichend);

  return new_obj;
}
Пример #12
0
/*! \brief read a bus object from a char buffer
 *  \par Function Description
 *  This function reads a bus object from the buffer \a buf.
 *  If the bus object was read successfully, a new bus object is
 *  allocated and appended to the \a object_list.
 *  
 *  \param [in] toplevel     The TOPLEVEL object
 *  \param [in] buf          a text buffer (usually a line of a schematic file)
 *  \param [in] release_ver  The release number gEDA
 *  \param [in] fileformat_ver a integer value of the file format
 *  \return The object list, or NULL on error.
 */
OBJECT *o_bus_read (TOPLEVEL *toplevel, const char buf[],
                    unsigned int release_ver, unsigned int fileformat_ver, GError **err)
{
  OBJECT *new_obj;
  char type; 
  int x1, y1;
  int x2, y2;
  int color;
  int ripper_dir;

  if (release_ver <= VERSION_20020825) {
    if (sscanf (buf, "%c %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color) != 6) {
      g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse bus object"));
      return NULL;
    }
    ripper_dir = 0;
  } else {
    if (sscanf (buf, "%c %d %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color,
		&ripper_dir) != 7) {
      g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse bus object"));
      return NULL;
    }
  }

  if (x1 == x2 && y1 == y2) {
    s_log_message (_("Found a zero length bus [ %c %d %d %d %d %d ]\n"),
                    type, x1, y1, x2, y2, color);
  }

  if (toplevel->override_bus_color != -1) {
    color = toplevel->override_bus_color;
  }

  if (color < 0 || color > MAX_COLORS) {
    s_log_message (_("Found an invalid color [ %s ]\n"), buf);
    s_log_message (_("Setting color to default color\n"));
    color = DEFAULT_COLOR;
  }

  if (ripper_dir < -1 || ripper_dir > 1) {
    s_log_message (_("Found an invalid bus ripper direction [ %s ]\n"), buf);
    s_log_message (_("Resetting direction to neutral (no direction)\n"));
    ripper_dir = 0;
  }

  new_obj = o_bus_new (toplevel, type, color, x1, y1, x2, y2, ripper_dir);

  return new_obj;
}
Пример #13
0
/* this cannot be called recursively */
void o_unlock(GschemToplevel *w_current)
{
  OBJECT *object = NULL;
  GList *s_current = NULL;

  s_current = geda_list_get_glist( w_current->toplevel->page_current->selection_list );

  while(s_current != NULL) {
    object = (OBJECT *) s_current->data;
    if (object) {
      /* only unlock if the object is locked */
      if (object->selectable == FALSE) {
        object->selectable = TRUE;
        object->color = object->locked_color;
        object->locked_color = -1;
        gschem_toplevel_page_content_changed (w_current, w_current->toplevel->page_current);
      } else {
        s_log_message(_("Object already unlocked\n"));
      }
    }

    s_current = g_list_next(s_current);
  }
  o_undo_savestate_old(w_current, UNDO_ALL);
}
Пример #14
0
/* This locks the entire selected list.  It does lock components, but does NOT
 * change the color (of primatives of the components) though
 * this cannot be called recursively */
void o_lock(GSCHEM_TOPLEVEL *w_current)
{
  OBJECT *object = NULL;
  GList *s_current = NULL;

  /* skip over head */
  s_current = geda_list_get_glist( w_current->toplevel->page_current->selection_list );

  while(s_current != NULL) {
    object = (OBJECT *) s_current->data;
    if (object) {
      /* check to see if locked_color is already being used */
      if (object->locked_color == -1) {
        object->selectable = FALSE;
        object->locked_color = object->color;
        object->color = LOCK_COLOR;
        w_current->toplevel->page_current->CHANGED=1;
      } else {
        s_log_message(_("Object already locked\n"));
      }
    }

    s_current = g_list_next(s_current);
  }

  if (!w_current->SHIFTKEY) o_select_unselect_all(w_current);
  o_undo_savestate(w_current, UNDO_ALL);
  i_update_menus(w_current);
}
Пример #15
0
/* this cannot be called recursively */
void o_unlock(GSCHEM_TOPLEVEL *w_current)
{
  OBJECT *object = NULL;
  GList *s_current = NULL;

  s_current = geda_list_get_glist( w_current->toplevel->page_current->selection_list );

  while(s_current != NULL) {
    object = (OBJECT *) s_current->data;
    if (object) {
      /* only unlock if the object is locked */
      if (object->selectable == FALSE) {
        object->selectable = TRUE;
        object->color = object->locked_color;
        object->locked_color = -1;
        w_current->toplevel->page_current->CHANGED = 1;
      } else {
        s_log_message(_("Object already unlocked\n"));
      }
    }

    s_current = g_list_next(s_current);
  }
  o_undo_savestate(w_current, UNDO_ALL);
}
Пример #16
0
/*! \brief embed an object into a schematic
 *  \par Function Description
 *  This functions embeds an object \a o_current into a
 *  libgeda. Currently complex objects are just marked to
 *  be embedded later. Picture objects are embedded immediatly.
 *
 *  \param toplevel  The TOPLEVEL object
 *  \param o_current The OBJECT to embed
 */
void o_embed(TOPLEVEL *toplevel, OBJECT *o_current)
{
  PAGE *page = o_get_page_compat (toplevel, o_current);
  int page_modified = 0;

  /* check o_current is a complex and is not already embedded */
  if (o_current->type == OBJ_COMPLEX &&
      !o_complex_is_embedded (o_current))
  {

    /* set the embedded flag */
    o_current->complex_embedded = TRUE;

    s_log_message (_("Component [%s] has been embedded\n"),
                   o_current->complex_basename);
    page_modified = 1;
  }

  /* If it's a picture and it's not embedded */
  if ( (o_current->type == OBJ_PICTURE) &&
       !o_picture_is_embedded (toplevel, o_current) ) {
    o_picture_embed (toplevel, o_current);

    page_modified = 1;
  }

  if (page_modified && page != NULL) {
    /* page content has been modified */
    page->CHANGED = 1;
  }
}
Пример #17
0
/*! \brief Get symbol data from a Scheme-based component source.
 *  \par Function Description
 *  Get symbol data from a Scheme-based component source.  The return
 *  value should be free()'d when no longer needed.
 *
 *  Private function used only in s_clib.c.
 *
 *  \param symbol Symbol to get data for.
 *  \return Allocated buffer containing symbol data.
 */
static gchar *get_data_scm (const CLibSymbol *symbol)
{
  SCM symdata;
  char *tmp;
  gchar *result;

  g_return_val_if_fail ((symbol != NULL), NULL);
  g_return_val_if_fail ((symbol->source->type == CLIB_SCM), NULL);

  symdata = scm_call_1 (symbol->source->get_fn,
			scm_from_utf8_string (symbol->name));

  if (!scm_is_string (symdata)) {
    s_log_message (_("Failed to load symbol data [%1$s] from source [%2$s]"),
                   symbol->name, symbol->source->name);
    return NULL;
  }

  /* Need to make sure that the correct free() function is called
   * on strings allocated by Guile. */
  tmp = scm_to_utf8_string (symdata);
  result = g_strdup(tmp);
  free (tmp);

  return result;
}
Пример #18
0
/*! \brief Modify the description of a circle OBJECT.
 *  \par Function Description
 *  This function modifies the description of the circle object <B>*object</B>
 *  depending on <B>whichone</B> that give the meaning of the <B>x</B> and <B>y</B>
 *  parameters.
 *
 *  If <B>whichone</B> is equal to <B>CIRCLE_CENTER</B>, the new center of the
 *  circle is given by (<B>x</B>,<B>y</B>) where <B>x</B> and <B>y</B> are in world units.
 *
 *  If <B>whichone</B> is equal to <B>CIRCLE_RADIUS</B>, the radius is given by
 *  <B>x</B> - in world units. <B>y</B> is ignored.
 *
 *  The bounding box of the circle object is updated after the modification of its
 *  parameters.
 *
 *  \param [in]     toplevel  The TOPLEVEL object.
 *  \param [in,out] object     Circle OBJECT to modify.
 *  \param [in]     x          New center x coordinate, or radius value.
 *  \param [in]     y          New center y coordinate.
 *                             Unused if radius is being modified.
 *  \param [in]     whichone   Which circle parameter to modify.
 *
 *  <B>whichone</B> can have the following values:
 *  <DL>
 *    <DT>*</DT><DD>CIRCLE_CENTER
 *    <DT>*</DT><DD>CIRCLE_RADIUS
 *  </DL>
 */
void o_circle_modify(TOPLEVEL *toplevel, OBJECT *object,
                     int x, int y, int whichone)
{
    o_emit_pre_change_notify (toplevel, object);

    switch(whichone) {
    case CIRCLE_CENTER:
        /* modify the center of the circle */
        object->circle->center_x = x;
        object->circle->center_y = y;
        break;
    case CIRCLE_RADIUS:
        /* modify the radius of the circle */
        if (x == 0) {
            s_log_message(_("Null radius circles are not allowed\n"));
            return;
        }
        object->circle->radius = x;
        break;
    default:
        break;
    }

    /* recalculate the boundings */
    o_circle_recalc(toplevel, object);
    o_emit_change_notify (toplevel, object);
}
Пример #19
0
/*! \brief Select a script and execute it
 *  \par Function Description
 *  This function opens a file selection dialog. The selected script 
 *  is executed.
 */
void setup_script_selector (GSCHEM_TOPLEVEL *w_current)
{
  char *filename;

  w_current->sowindow =
    gtk_file_chooser_dialog_new (_("Execute Script..."),
				 GTK_WINDOW(w_current->main_window),
				 GTK_FILE_CHOOSER_ACTION_OPEN,
				 GTK_STOCK_CANCEL, 
				 GTK_RESPONSE_CANCEL,
				 GTK_STOCK_EXECUTE, 
				 GTK_RESPONSE_ACCEPT,
				 NULL);

  /* Set the alternative button order (ok, cancel, help) for other systems */
  gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->sowindow),
					  GTK_RESPONSE_ACCEPT,
					  GTK_RESPONSE_CANCEL,
					  -1);

  if (gtk_dialog_run (GTK_DIALOG (w_current->sowindow)) == GTK_RESPONSE_ACCEPT) {
    filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (w_current->sowindow));

    if (!(g_file_test(filename, G_FILE_TEST_IS_DIR))) {
      s_log_message(_("Executing guile script [%s]\n"), filename);
      g_read_file(filename);
    }
    g_free (filename);
  }

  gtk_widget_destroy (GTK_WIDGET(w_current->sowindow));
  w_current->sowindow = NULL;
}
Пример #20
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);

}
Пример #21
0
/* Error handler function used by x_rc_parse_gschem(). */
static void
x_rc_parse_gschem_error (GError **err, GSCHEM_TOPLEVEL *w_current)
{
  char *msg2; /* Secondary text */
  GtkWidget *dialog;

  g_assert (w_current != NULL);
  g_assert (err != NULL);

  /* Take no chances; if err was not set for some reason, it's a
   * problem. */
  if (*err == NULL) {
    /* Log message */
    s_log_message (_("ERROR: An unknown error occurred while parsing "
                     "configuration files.\n"));

    /* Dialog message */
    msg2 =
      g_strdup (_("An unknown error occurred while parsing configuration files."
                  "\n\nThe gschem log may contain more information."));
  } else {

    /* Config files are allowed to be missing or skipped; check for
     * this. */
    if (g_error_matches (*err, G_FILE_ERROR, G_FILE_ERROR_NOENT) ||
        g_error_matches (*err, EDA_ERROR, EDA_ERROR_RC_TWICE)) {
      return;
    }

    /* Log message */
    s_log_message (_("ERROR: %s\n"), (*err)->message);

    /* Dialog message */
    msg2 = g_strdup_printf (_("%s\n\n"
                              "The gschem log may contain more information."),
                            (*err)->message);
  }

  dialog = gtk_message_dialog_new (GTK_WINDOW (w_current->main_window),
                                   GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
                                   GTK_BUTTONS_OK,
                                   _("Cannot load gschem configuration."));
  g_object_set (G_OBJECT (dialog), "secondary-text", msg2, NULL);
  gtk_dialog_run (GTK_DIALOG (dialog));
  gtk_widget_destroy (dialog);
  g_free (msg2);
}
Пример #22
0
/*! \brief Closes a page.
 *  \par Function Description
 *  This function closes the page <B>page</B> of toplevel
 *  <B>toplevel</B>.
 *
 *  If necessary, the current page of <B>toplevel</B> is changed to
 *  the next valid page or to a new untitled page.
 *
 *  \param [in] w_current The toplevel environment.
 *  \param [in] page      The page to close.
 */
void
x_window_close_page (GSCHEM_TOPLEVEL *w_current, PAGE *page)
{
  TOPLEVEL *toplevel = w_current->toplevel;
  PAGE *new_current = NULL;
  GList *iter;

  g_return_if_fail (toplevel != NULL);
  g_return_if_fail (page     != NULL);

  g_assert (page->pid != -1);

  /* If we're closing whilst inside a move action, re-wind the
   * page contents back to their state before we started */
  if (w_current->inside_action &&
      (w_current->event_state == MOVE ||
       w_current->event_state == ENDMOVE)) {
    o_move_cancel (w_current);
  }

  if (page == toplevel->page_current) {
    /* as it will delete current page, select new current page */
    /* first look up in page hierarchy */
    new_current = s_page_search_by_page_id (toplevel->pages, page->up);

    if (new_current == NULL) {
      /* no up in hierarchy, choice is prev, next, new page */
      iter = g_list_find( geda_list_get_glist( toplevel->pages ), page );

      if ( g_list_previous( iter ) ) {
        new_current = (PAGE *)g_list_previous( iter )->data;
      } else if ( g_list_next( iter ) ) {
        new_current = (PAGE *)g_list_next( iter )->data;
      } else {
        /* need to add a new untitled page */
        new_current = NULL;
      }
    }
    /* new_current will be the new current page at the end of the function */
  }

  s_log_message (page->CHANGED ?
                 _("Discarding page [%s]\n") : _("Closing [%s]\n"),
                 page->page_filename);
  /* remove page from toplevel list of page and free */
  s_page_delete (toplevel, page);

  /* Switch to a different page if we just removed the current */
  if (toplevel->page_current == NULL) {

    /* Create a new page if there wasn't another to switch to */
    if (new_current == NULL) {
      new_current = x_window_open_page (w_current, NULL);
    }

    /* change to new_current and update display */
    x_window_set_current_page (w_current, new_current);
  }
}
Пример #23
0
/*! \brief Create a character string representation of a picture OBJECT.
 *  \par Function Description
 *  This function formats a string in the buffer <B>*buff</B> to describe
 *  the picture object <B>*object</B>.
 *
 *  \param [in] object  Picture OBJECT to create string from.
 *  \return A pointer to the picture OBJECT character string.
 *
 *  \note
 *  Caller must g_free returned character string.
 *
 */
char *o_picture_save(OBJECT *object)
{
  int width, height, x1, y1;
  gchar *encoded_picture=NULL;
  gchar *out=NULL;
  guint encoded_picture_length;

  /* calculate the width and height of the box */
  width  = abs(object->picture->lower_x - object->picture->upper_x); 
  height = abs(object->picture->upper_y - object->picture->lower_y);

  /* calculate the lower left corner of the box */
  x1 = object->picture->upper_x;
  y1 = object->picture->upper_y - height; /* move the origin to 0, 0*/

#if DEBUG
  printf("picture: %d %d %d %d\n", x1, y1, width, height);
#endif

  /* Encode the picture if it's embedded */
  if (object->picture->embedded == 1) {
    encoded_picture =
      s_encoding_base64_encode( (char *)object->picture->file_content,
                                object->picture->file_length,
                                &encoded_picture_length,
                                TRUE);
    if (encoded_picture == NULL) {
      s_log_message(_("ERROR: o_picture_save: unable to encode the picture.\n"));
    }
  }

  if (object->picture->embedded==1 &&
      encoded_picture != NULL) {
    out = g_strdup_printf("%c %d %d %d %d %d %c %c\n%s\n%s\n%s", 
			  object->type,
			  x1, y1, width, height,
			  object->picture->angle,
			  /* Convert the (0,1) chars to ASCII */
			  (object->picture->mirrored)+0x30, 
			  object->picture->embedded+0x30, 
			  object->picture->filename,
			  encoded_picture,
			  ".");
  }
  else {
    out = g_strdup_printf("%c %d %d %d %d %d %c %c\n%s", 
			  object->type,
			  x1, y1, width, height,
			  object->picture->angle,
			  /* Convert the (0,1) chars to ASCII */
			  (object->picture->mirrored)+0x30, 
			  object->picture->embedded+0x30, 
			  object->picture->filename);
  }
  g_free(encoded_picture);

  return(out);
}
Пример #24
0
/*! \brief Embed the image file associated with a picture
 *
 *  \par Function Description
 *  This function reads and embeds image file associated with the picture.
 *
 *  \param [in]     toplevel     The TOPLEVEL object.
 *  \param [in]     object       The picture OBJECT to embed
 */
void o_picture_embed (TOPLEVEL *toplevel, OBJECT *object)
{
  GError *err = NULL;
  GdkPixbuf *pixbuf;
  gchar *filename;

  /* Free any existing embedded data */
  g_free (object->picture->file_content);
  object->picture->file_content = NULL;

  g_file_get_contents (object->picture->filename,
                       &object->picture->file_content,
                       &object->picture->file_length,
                       &err);
  if (err != NULL) {
    s_log_message (_("Failed to load image from file [%s]: %s\n"),
                   object->picture->filename, err->message);
    g_error_free (err);
    return;
  }

  object->picture->embedded = 1;

  pixbuf = o_picture_pixbuf_from_buffer (object->picture->file_content,
                                         object->picture->file_length,
                                         &err);
  if (err != NULL) {
    s_log_message (_("Failed to load image from embedded data [%s]: %s\n"),
                   object->picture->filename, err->message);
    s_log_message (_("Falling back to file loading. Picture unembedded.\n"));
    g_error_free (err);
    object->picture->embedded = 0;
    return;
  }

  /* Change to the new pixbuf loaded before we embedded. */
  if (object->picture->original_picture != NULL)
    g_object_unref(object->picture->original_picture);

  object->picture->original_picture = pixbuf;

  filename = g_path_get_basename(object->picture->filename);
  s_log_message (_("Picture [%s] has been embedded\n"), filename);
  g_free(filename);
}
Пример #25
0
/*! \brief Execute a library command.
 *  \par Function Description
 *  Execute a library command, returning the standard output, or \b
 *  NULL if the command fails for some reason.  The system \b PATH is
 *  used to find the program to execute.
 *  The command can write messages to the standard error output. They
 *  are forwarded to the libgeda logging mechanism.
 *
 *  Private function used only in s_clib.c.
 *
 *  \todo This is probably generally useful.
 *
 *  \param command  Command string to execute.
 *  \return The program's output, or \b NULL on failure.
 */
static gchar *run_source_command (const gchar *command)
{
  gchar *standard_output = NULL;
  gchar *standard_error = NULL;
  gint exit_status;
  GError *e = NULL;
  gboolean success = FALSE;

  g_return_val_if_fail((command != NULL), NULL);

  g_spawn_command_line_sync (command,
                             &standard_output,
                             &standard_error,
                             &exit_status,
                             &e);

  if (e != NULL) {
    s_log_message (_("Library command failed [%1$s]: %2$s"), command,
		   e->message);
    g_error_free (e);

  } else if (WIFSIGNALED(exit_status)) {
    s_log_message (_("Library command failed [%1$s]: Uncaught signal %2$i."),
                   command, WTERMSIG(exit_status));

  } else if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status)) {
    s_log_message (_("Library command failed [%1$s]"), command);
    s_log_message(_("Error output was:\n%1$s"), standard_error);

  } else {
    success = TRUE;
  }

  /* forward library command messages */
  if (success && standard_error != NULL)
    s_log_message ("%s", standard_error);

  g_free (standard_error);

  if (success) return standard_output;

  g_free (standard_output);
  return NULL;
}
Пример #26
0
/*! \brief unembed an object from a schematic
 *  \par Function Description
 *  This functions unembeds an object \a o_current from a
 *  libgeda structure. Complex objects are just marked to
 *  be not embedded. Picture objects are unembeded immediatly.
 *
 *  \param toplevel  The TOPLEVEL object
 *  \param o_current The OBJECT to unembed
 */
void o_unembed(TOPLEVEL *toplevel, OBJECT *o_current)
{
  const CLibSymbol *sym;
  PAGE *page = o_get_page_compat (toplevel, o_current);
  int page_modified = 0;
  
  /* check o_current is an embedded complex */
  if (o_current->type == OBJ_COMPLEX &&
      o_complex_is_embedded (o_current))
  {
        
    /* search for the symbol in the library */
    sym = s_clib_get_symbol_by_name (o_current->complex_basename);

    if (sym == NULL) {
      /* symbol not found in the symbol library: signal an error */
      s_log_message (_("Could not find component [%s], while trying to "
                       "unembed. Component is still embedded\n"),
                     o_current->complex_basename);
      
    } else {
      /* clear the embedded flag */
      o_current->complex_embedded = FALSE;

      s_log_message (_("Component [%s] has been successfully unembedded\n"),
                     o_current->complex_basename);
      
      page_modified = 1;
    }
  }

  /* If it's a picture and it's embedded */
  if ( (o_current->type == OBJ_PICTURE) &&
       o_picture_is_embedded (toplevel, o_current)) {
    o_picture_unembed (toplevel, o_current);

    page_modified = 1;
  }

  if (page_modified && page != NULL) {
    page->CHANGED = 1;
  }
}
Пример #27
0
/*! \brief Search for the parent page of a page in hierarchy.
 *  \par Function Description
 *  This function searches the parent page of page \a page in the
 *  hierarchy. It checks all the pages in the list \a page_list.
 *
 *  It returns a pointer on the page if found, NULL otherwise.
 *
 *  \note
 *  The page \a current_page must be in the list \a page_list.
 *
 *  \param [in] page_list    The list of pages in which to search.
 *  \param [in] current_page The reference page for the search.
 *  \returns A pointer on the page found or NULL if not found.
 */
PAGE *
s_hierarchy_find_up_page (GedaPageList *page_list, PAGE *current_page)
{
  if (current_page->up < 0) {
    s_log_message(_("There are no schematics above the current one!\n"));
    return NULL;
  }

  return s_page_search_by_page_id (page_list, current_page->up);
}
Пример #28
0
/*! \brief Saves a page to a file.
 *  \par Function Description
 *  This function saves the page <B>page</B> to a file named
 *  <B>filename</B>.
 *
 *  It returns the value returned by function <B>f_save()</B> trying
 *  to save page <B>page</B> to file <B>filename</B> (1 on success, 0
 *  on failure).
 *
 *  <B>page</B> may not be the current page of <B>toplevel</B>. The
 *  current page of <B>toplevel</B> is not affected by this function.
 *
 *  \param [in] toplevel The toplevel environment.
 *  \param [in] page     The page to save.
 *  \param [in] filename The name of the file in which to save page.
 *  \returns 1 on success, 0 otherwise.
 */
gint
x_window_save_page (GSCHEM_TOPLEVEL *w_current, PAGE *page, const gchar *filename)
{
  TOPLEVEL *toplevel = w_current->toplevel;
  PAGE *old_current;
  const gchar *log_msg, *state_msg;
  gint ret;

  g_return_val_if_fail (toplevel != NULL, 0);
  g_return_val_if_fail (page     != NULL, 0);
  g_return_val_if_fail (filename != NULL, 0);

  /* save current page for restore after opening */
  old_current = toplevel->page_current;

  /* change to page */
  s_page_goto (toplevel, page);
  /* and try saving current page to filename */
  ret = (gint)f_save (toplevel, filename);
  if (ret != 1) {
    /* an error occured when saving page to file */
    log_msg   = _("Could NOT save page [%s]\n");
    state_msg = _("Error while trying to save");

  } else {
    /* successful save of page to file, update page... */
    /* change page name if necessary and prepare log message */
    if (g_ascii_strcasecmp (page->page_filename, filename) != 0) {
      g_free (page->page_filename);
      page->page_filename = g_strdup (filename);

      log_msg = _("Saved as [%s]\n");
    } else {
      log_msg = _("Saved [%s]\n");
    }
    state_msg = _("Saved");

    /* reset page CHANGED flag */
    page->CHANGED = 0;

    /* update recent file list */
    recent_files_add(filename);
  }

  /* log status of operation */
  s_log_message (log_msg, filename);

  /* update display and page manager */
  x_window_set_current_page (w_current, old_current);

  i_set_state_msg  (w_current, SELECT, state_msg);
  i_update_toolbar (w_current);

  return ret;
}
Пример #29
0
/*! \brief Embed the image file associated with a picture
 * \par Function Description
 * Verify that a picture has valid data associated with it, and if so,
 * mark it to be embedded.
 *
 *  \param [in]     toplevel     The TOPLEVEL object.
 *  \param [in]     object       The picture OBJECT to embed
 */
void o_picture_embed (TOPLEVEL *toplevel, OBJECT *object)
{
  const gchar *filename = o_picture_get_filename (object);
  gchar *basename;

  if (o_picture_is_embedded (object)) return;

  if (object->picture->file_content == NULL) {
    s_log_message (_("Picture [%1$s] has no image data."), filename);
    s_log_message (_("Falling back to file loading. Picture is still unembedded."));
    object->picture->embedded = 0;
    return;
  }

  object->picture->embedded = 1;

  basename = g_path_get_basename (filename);
  s_log_message (_("Picture [%1$s] has been embedded."), basename);
  g_free (basename);
}
Пример #30
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 */
void o_edit_show_hidden (GSCHEM_TOPLEVEL *w_current, const GList *o_list)
{
  /* this function just shows the hidden text, but doesn't toggle it */
  /* this function does not change the CHANGED bit, no real changes are */
  /* made to the schematic */

  /* toggle show_hidden_text variable, which when it is true */
  /* means that hidden text IS drawn */
  w_current->toplevel->show_hidden_text = !w_current->toplevel->show_hidden_text;
  i_show_state(w_current, NULL); /* update screen status */

  o_edit_show_hidden_lowlevel(w_current, o_list);
  o_invalidate_all (w_current);

  if (w_current->toplevel->show_hidden_text) {
    s_log_message(_("Hidden text is now visible\n"));
  } else {
    s_log_message(_("Hidden text is now invisible\n"));
  }
}