示例#1
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 */
void
s_hierarchy_down_symbol (TOPLEVEL *toplevel, const CLibSymbol *symbol,
                         PAGE *parent)
{
  PAGE *page;
  gchar *filename;

  filename = s_clib_symbol_get_filename (symbol);

  page = s_page_search (toplevel, filename);
  if (page) {
    /* change link to parent page since we
     * can come here from any parent and must
     * come back to the same page */
    page->up = parent->pid;
    s_page_goto (toplevel, page);
    g_free (filename);
    return;
  }

  page = s_page_new (toplevel, filename);
  g_free(filename);

  s_page_goto (toplevel, page);

  f_open(toplevel, page, s_page_get_filename (page), NULL);

  page->up = parent->pid;
  page_control_counter++;
  page->page_control = page_control_counter;

}
示例#2
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 */
void
s_hierarchy_down_symbol (TOPLEVEL *toplevel, const CLibSymbol *symbol,
                         PAGE *parent)
{
  PAGE *page;
  gchar *filename;

  filename = s_clib_symbol_get_filename (symbol);

  page = s_page_search (toplevel, filename);
  if (page) {
    s_page_goto (toplevel, page);
    g_free (filename);
    return;
  }

  page = s_page_new (toplevel, filename);
  g_free(filename);

  s_page_goto (toplevel, page);

  f_open(toplevel, page, page->page_filename, NULL);

  page->up = parent->pid;
  page_control_counter++;
  page->page_control = page_control_counter;

}
示例#3
0
/*! \brief Load a subpage
 *
 *  \par Function Description
 *  Implements s_hierarchy_down_schematic(), but without changing variables
 *  related to the UI.
 *
 *  - Ensures a duplicate page is not loaded
 *  - Does not change the current page
 *  - Does not modify the most recent "up" page
 *
 *  \param [in]  page
 *  \param [in]  filename
 *  \param [out] error
 *  \return A pointer to the subpage or NULL if an error occured.
 */
PAGE*
s_hierarchy_load_subpage (PAGE *page, const char *filename, GError **error)
{
  char *string;
  PAGE *subpage = NULL;

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

  SCM string_s = scm_call_1 (scm_c_public_ref ("geda library",
                                               "get-source-library-file"),
                             scm_from_utf8_string (filename));

  if (scm_is_false (string_s)) {
    g_set_error (error,
                 EDA_ERROR,
                 EDA_ERROR_NOLIB,
                 _("Schematic not found in source library."));
  } else {
    string = scm_to_utf8_string (string_s);
    gchar *normalized = f_normalize_filename (string, error);

    subpage = s_page_search (page->toplevel, normalized);

    if (subpage == NULL) {
      int success;

      subpage = s_page_new (page->toplevel, string);
      success = f_open (page->toplevel, subpage, s_page_get_filename (subpage), error);

      if (success) {
        subpage->page_control = ++page_control_counter;
      } else {
        s_page_delete (page->toplevel, subpage);
        subpage = NULL;
      }
    }

    g_free (normalized);
  }

  return subpage;
}
示例#4
0
/*! \brief Load a subpage
 *
 *  \par Function Description
 *  Implements s_hierarchy_down_schematic(), but without changing variables
 *  related to the UI.
 *
 *  - Ensures a duplicate page is not loaded
 *  - Does not change the current page
 *  - Does not modify the most recent "up" page
 *
 *  \param [in]  page
 *  \param [in]  filename
 *  \param [out] error
 *  \return A pointer to the subpage or NULL if an error occured.
 */
PAGE*
s_hierarchy_load_subpage (PAGE *page, const char *filename, GError **error)
{
  char *string;
  PAGE *subpage = NULL;

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

  string = s_slib_search_single (filename);

  if (string == NULL) {
    g_set_error (error,
                 EDA_ERROR,
                 EDA_ERROR_NOLIB,
                 _("Schematic not found in source library."));
  } else {
    gchar *normalized = f_normalize_filename (string, error);

    subpage = s_page_search (page->toplevel, normalized);

    if (subpage == NULL) {
      int success;

      subpage = s_page_new (page->toplevel, string);
      success = f_open (page->toplevel, subpage, subpage->page_filename, error);

      if (success) {
        subpage->page_control = ++page_control_counter;
      } else {
        s_page_delete (page->toplevel, subpage);
        subpage = NULL;
      }
    }

    g_free (normalized);
  }

  return subpage;
}
示例#5
0
/*! \brief Opens a new page from a file.
 *  \par Function Description
 *  This function opens the file whose name is <B>filename</B> in a
 *  new PAGE of <B>toplevel</B>.
 *
 *  If there is no page for <B>filename</B> in <B>toplevel</B>'s list
 *  of pages, it creates a new PAGE, loads the file in it and returns
 *  a pointer on the new page. Otherwise it returns a pointer on the
 *  existing page.
 *
 *  If the filename passed is NULL, this function creates an empty,
 *  untitled page.  The name of the untitled page is build from
 *  configuration data ('untitled-name') and a counter for uniqueness.
 *
 *  The opened page becomes the current page of <B>toplevel</B>.
 *
 *  \param [in] w_current The toplevel environment.
 *  \param [in] filename The name of the file to open or NULL for a blank page.
 *  \returns A pointer on the new page.
 *
 *  \bug This code should check to make sure any untitled filename
 *  does not conflict with a file on disk.
 */
PAGE*
x_window_open_page (GschemToplevel *w_current, const gchar *filename)
{
  TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
  GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current);
  PAGE *page;
  gchar *fn;

  g_return_val_if_fail (toplevel != NULL, NULL);

  /* Generate untitled filename if none was specified */
  if (filename == NULL) {
    gchar *cwd, *tmp, *untitled_name;
    EdaConfig *cfg;
    cwd = g_get_current_dir ();
    cfg = eda_config_get_context_for_path (cwd);
    untitled_name = eda_config_get_string (cfg, "gschem", "default-filename", NULL);
    tmp = g_strdup_printf ("%s_%d.sch",
                           untitled_name,
                           ++w_current->num_untitled);
    fn = g_build_filename (cwd, tmp, NULL);
    g_free (untitled_name);
    g_free(cwd);
    g_free(tmp);
  } else {
    fn = g_strdup (filename);
  }

  /* Return existing page if it is already loaded */
  page = s_page_search (toplevel, fn);
  if ( page != NULL ) {
    g_free(fn);
    return page;
  }

  page = s_page_new (toplevel, fn);
  s_page_goto (toplevel, page);
  gschem_toplevel_page_changed (w_current);

  /* Load from file if necessary, otherwise just print a message */
  if (filename != NULL) {
    GError *err = NULL;
    if (!quiet_mode)
      s_log_message (_("Loading schematic [%s]\n"), fn);

    if (!f_open (toplevel, page, (gchar *) fn, &err)) {
      GtkWidget *dialog;

      g_warning ("%s\n", err->message);
      dialog = gtk_message_dialog_new_with_markup
        (GTK_WINDOW (w_current->main_window),
         GTK_DIALOG_DESTROY_WITH_PARENT,
         GTK_MESSAGE_ERROR,
         GTK_BUTTONS_CLOSE,
         _("<b>An error occurred while loading the requested file.</b>\n\nLoading from '%s' failed: %s. The gschem log may contain more information."),
         fn, err->message);
      gtk_window_set_title (GTK_WINDOW (dialog), _("Failed to load file"));
      gtk_dialog_run (GTK_DIALOG (dialog));
      gtk_widget_destroy (dialog);
      g_error_free (err);
    } else {
      gtk_recent_manager_add_item (recent_manager, g_filename_to_uri(fn, NULL, NULL));
    }
  } else {
    if (!quiet_mode)
      s_log_message (_("New file [%s]\n"),
                     toplevel->page_current->page_filename);

    g_run_hook_page (w_current, "%new-page-hook", toplevel->page_current);
  }

  gschem_page_view_set_page (page_view,
                             toplevel->page_current);

  o_undo_savestate (w_current, toplevel->page_current, UNDO_ALL);

  /* This line is generally un-needed, however if some code
   * wants to open a page, yet not bring it to the front, it is
   * needed needed to add it into the page manager. Otherwise,
   * it will get done in x_window_set_current_page(...)
   */
  x_pagesel_update (w_current); /* ??? */

  g_free (fn);

  return page;
}
示例#6
0
/*!
 *  \brief Search for schematic associated source files and load them.
 *  \par Function Description
 *  This function searches the associated source file refered by the
 *  <B>filename</B> and loads it.  If the <B>flag</B> is set to
 *  <B>HIERARCHY_NORMAL_LOAD</B> and the page is already in the list of
 *  pages it will return the <B>pid</B> of that page.
 *  If the <B>flag</B> is set to <B>HIERARCHY_FORCE_LOAD</B> then this
 *  function will load the page again with a new page id. The second case
 *  is mainly used by gnetlist where pushed down schematics MUST be unique.
 *
 *  \param [in] toplevel      The TOPLEVEL object.
 *  \param [in] filename      Schematic file name.
 *  \param [in] parent        The parent page of the schematic.
 *  \param [in] page_control
 *  \param [in] flag          sets whether to force load
 *  \param [out] err         Location to return a GError on failure.
 *  \return The page loaded, or NULL if failed.
 *
 *  \note
 *  This function finds the associated source files and
 *  loads all up
 *  It only works for schematic files though
 *  this is basically push
 *  flag can either be HIERARCHY_NORMAL_LOAD or HIERARCHY_FORCE_LOAD
 *  flag is mainly used by gnetlist where pushed down schematics MUST be unique
 */
PAGE *
s_hierarchy_down_schematic_single(TOPLEVEL *toplevel, const gchar *filename,
                                  PAGE *parent, int page_control, int flag,
                                  GError **err)
{
  gchar *string;
  PAGE *found = NULL;
  PAGE *forbear;

  g_return_val_if_fail ((toplevel != NULL), NULL);
  g_return_val_if_fail ((filename != NULL), NULL);
  g_return_val_if_fail ((parent != NULL), NULL);

  SCM string_s = scm_call_1 (scm_c_public_ref ("geda library",
                                               "get-source-library-file"),
                             scm_from_utf8_string (filename));

  if (scm_is_false (string_s)) {
    g_set_error (err, EDA_ERROR, EDA_ERROR_NOLIB,
                 _("Schematic not found in source library."));
    return NULL;
  }

  string = scm_to_utf8_string (string_s);

  switch (flag) {
  case HIERARCHY_NORMAL_LOAD:
    {
      gchar *filename = f_normalize_filename (string, NULL);
      found = s_page_search (toplevel, filename);
      g_free (filename);

      if (found) {
        /* check whether this page is in the parents list */
        for (forbear = parent;
             forbear != NULL && found->pid != forbear->pid && forbear->up >= 0;
             forbear = s_page_search_by_page_id (toplevel->pages, forbear->up))
          ; /* void */

        if (forbear != NULL && found->pid == forbear->pid) {
          g_set_error (err, EDA_ERROR, EDA_ERROR_LOOP,
                       _("Hierarchy contains a circular dependency."));
          return NULL;  /* error signal */
        }
        s_page_goto (toplevel, found);
        if (page_control != 0) {
          found->page_control = page_control;
        }
        found->up = parent->pid;
        g_free (string);
        return found;
      }

      found = s_page_new (toplevel, string);

      f_open (toplevel, found, s_page_get_filename (found), NULL);
    }
    break;

  case HIERARCHY_FORCE_LOAD:
    {
      found = s_page_new (toplevel, string);
      f_open (toplevel, found, s_page_get_filename (found), NULL);
    }
    break;

  default:
    g_return_val_if_reached (NULL);
  }

  if (page_control == 0) {
    page_control_counter++;
    found->page_control = page_control_counter;
  } else {
    found->page_control = page_control;
  }

  found->up = parent->pid;

  g_free (string);

  return found;
}
示例#7
0
/*! \brief Opens a new page from a file.
 *  \par Function Description
 *  This function opens the file whose name is <B>filename</B> in a
 *  new PAGE of <B>toplevel</B>.
 *
 *  If there is no page for <B>filename</B> in <B>toplevel</B>'s list
 *  of pages, it creates a new PAGE, loads the file in it and returns
 *  a pointer on the new page. Otherwise it returns a pointer on the
 *  existing page.
 *
 *  If the filename passed is NULL, this function creates an empty,
 *  untitled page.  The name of the untitled page is build from
 *  configuration data ('untitled-name') and a counter for uniqueness.
 *
 *  The opened page becomes the current page of <B>toplevel</B>.
 *
 *  \param [in] w_current The toplevel environment.
 *  \param [in] filename The name of the file to open or NULL for a blank page.
 *  \returns A pointer on the new page.
 *
 *  \bug This code should check to make sure any untitled filename
 *  does not conflict with a file on disk.
 */
PAGE*
x_window_open_page (GSCHEM_TOPLEVEL *w_current, const gchar *filename)
{
  TOPLEVEL *toplevel = w_current->toplevel;
  PAGE *old_current, *page;
  gchar *fn;

  g_return_val_if_fail (toplevel != NULL, NULL);

  /* Generate untitled filename if none was specified */
  if (filename == NULL) {
    gchar *cwd, *tmp;
    cwd = g_get_current_dir ();
    tmp = g_strdup_printf ("%s_%d.sch",
                           toplevel->untitled_name,
                           ++w_current->num_untitled);
    fn = g_build_filename (cwd, tmp, NULL);
    g_free(cwd);
    g_free(tmp);
  } else {
    fn = g_strdup (filename);
  }

  /* Return existing page if it is already loaded */
  page = s_page_search (toplevel, fn);
  if ( page != NULL ) {
    g_free(fn);
    return page;
  }

  old_current = toplevel->page_current;
  page = s_page_new (toplevel, fn);
  s_page_goto (toplevel, page);

  /* Load from file if necessary, otherwise just print a message */
  if (filename != NULL) {
    GError *err = NULL;
    if (!quiet_mode)
      s_log_message (_("Loading schematic [%s]\n"), fn);

    if (!f_open (toplevel, page, (gchar *) fn, &err)) {
      GtkWidget *dialog;

      g_warning ("%s\n", err->message);
      dialog = gtk_message_dialog_new (GTK_WINDOW (w_current->main_window),
                                       GTK_DIALOG_DESTROY_WITH_PARENT,
                                       GTK_MESSAGE_ERROR,
                                       GTK_BUTTONS_CLOSE,
                                       "%s",
                                       err->message);
      gtk_window_set_title (GTK_WINDOW (dialog), _("Failed to load file"));
      gtk_dialog_run (GTK_DIALOG (dialog));
      gtk_widget_destroy (dialog);
      g_error_free (err);
    } else {
      gtk_recent_manager_add_item (recent_manager, g_filename_to_uri(fn, NULL, NULL));
    }
  } else {
    if (!quiet_mode)
      s_log_message (_("New file [%s]\n"),
                     toplevel->page_current->page_filename);
  }

  if (scm_is_false (scm_hook_empty_p (new_page_hook)))
    scm_run_hook (new_page_hook,
                  scm_cons (g_make_page_smob (toplevel, page), SCM_EOL));

  a_zoom_extents (w_current,
                  s_page_objects (toplevel->page_current),
                  A_PAN_DONT_REDRAW);

  o_undo_savestate (w_current, UNDO_ALL);

  if ( old_current != NULL )
    s_page_goto (toplevel, old_current);

  /* This line is generally un-needed, however if some code
   * wants to open a page, yet not bring it to the front, it is
   * needed needed to add it into the page manager. Otherwise,
   * it will get done in x_window_set_current_page(...)
   */
  x_pagesel_update (w_current); /* ??? */

  g_free (fn);

  return page;
}
示例#8
0
/*! \todo Finish function documentation!!!
 *  \brief Search for schematic associated source files and load them.
 *  \par Function Description
 *  This function searches the associated source file refered by the
 *  <B>filename</B> and loads it.  If the <B>flag</B> is set to
 *  <B>HIERARCHY_NORMAL_LOAD</B> and the page is allready in the list of
 *  pages it will return the <B>pid</B> of that page.
 *  If the <B>flag</B> is set to <B>HIERARCHY_FORCE_LOAD</B> then this
 *  function will load the page again with a new page id. The second case
 *  is mainly used by gnetlist where pushed down schematics MUST be unique.
 *
 *  \param [in] toplevel     The TOPLEVEL object.
 *  \param [in] filename      Schematic file name.
 *  \param [in] parent        The parent page of the schematic.
 *  \param [in] page_control
 *  \param [in] flag
 *  \return The page loaded, or NULL if failed.
 *
 *  \note
 *  This function goes and finds the associated source files and
 *  loads all up
 *  It only works for schematic files though
 *  this is basically push
 *  flag can either be HIERARCHY_NORMAL_LOAD or HIERARCHY_FORCE_LOAD
 *  flag is mainly used by gnetlist where pushed down schematics MUST be unique
 */
PAGE *
s_hierarchy_down_schematic_single(TOPLEVEL *toplevel, const gchar *filename,
                                  PAGE *parent, int page_control, int flag)
{
  gchar *string;
  PAGE *found = NULL;
  PAGE *forbear;

  g_return_val_if_fail ((toplevel != NULL), NULL);
  g_return_val_if_fail ((filename != NULL), NULL);
  g_return_val_if_fail ((parent != NULL), NULL);

  string = s_slib_search_single(filename);
  if (string == NULL) {
    return NULL;
  }

  switch (flag) {
  case HIERARCHY_NORMAL_LOAD:
    {
      gchar *filename = f_normalize_filename (string, NULL);
      found = s_page_search (toplevel, filename);
      g_free (filename);

      if (found) {
        /* check whether this page is in the parents list */
        for (forbear = parent;
             forbear != NULL && found->pid != forbear->pid && forbear->up >= 0;
             forbear = s_page_search_by_page_id (toplevel->pages, forbear->up))
          ; /* void */

        if (found->pid == forbear->pid) {
          s_log_message(_("hierarchy loop detected while visiting page:\n"
                          "  \"%s\"\n"), found->page_filename);
          return NULL;  /* error signal */
        }
        s_page_goto (toplevel, found);
        if (page_control != 0) {
          found->page_control = page_control;
        }
        found->up = parent->pid;
        g_free (string);
        return found;
      }

      found = s_page_new (toplevel, string);

      f_open (toplevel, found, found->page_filename, NULL);
    }
    break;

  case HIERARCHY_FORCE_LOAD:
    {
      found = s_page_new (toplevel, string);
      f_open (toplevel, found, found->page_filename, NULL);
    }
    break;
  }

  if (page_control == 0) {
    page_control_counter++;
    found->page_control = page_control_counter;
  } else {
    found->page_control = page_control;
  }

  found->up = parent->pid;

  g_free (string);

  return found;
}