Exemple #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) {
    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;

}
Exemple #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) {
    /* 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;

}
/*! \brief Asks for confirmation before closing a changed page.
 *  \par Function Description
 *  This function asks the user to confirm its closing order for
 *  page <B>page</B> while it still has unsaved changes.
 *
 *  It displays a message dialog inviting the user to cancel the
 *  closing, or to discard the changes or to save the changes to a
 *  file.
 *
 *  \param [in] w_current The toplevel environment.
 *  \param [in] page      The page to close.
 *
 *  \return TRUE if okay to continue with closing page, FALSE
 *  otherwise.
 */
gboolean
x_dialog_close_changed_page (GschemToplevel *w_current, PAGE *page)
{
  GtkWidget *dialog;
  PAGE *keep_page;
  gboolean result = FALSE;

  g_return_val_if_fail (page != NULL && page->CHANGED, TRUE);

  keep_page = w_current->toplevel->page_current;

  dialog = GTK_WIDGET (g_object_new (TYPE_CLOSE_CONFIRMATION_DIALOG,
                                     "unsaved-page", page,
                                     NULL));
  /* set default response signal. This is usually triggered by the
     "Return" key */
  gtk_dialog_set_default_response(GTK_DIALOG(dialog),
                                  GTK_RESPONSE_YES);

  switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
      case GTK_RESPONSE_NO:
        /* action selected: close without saving */
        /* close the page, discard changes */
        result = TRUE;
        break;


      case GTK_RESPONSE_YES:
        /* action selected: save */
        s_page_goto (w_current->toplevel, page);
        gschem_toplevel_page_changed (w_current);
        i_callback_file_save(w_current, 0, NULL);
        /* has the page been really saved? */
        if (!page->CHANGED) {
          result = TRUE;
        }
        /* no, user has cancelled the save and page has changes */
        /* do not close page */
        break;

      case GTK_RESPONSE_CANCEL:
        /* action selected: cancel */
        /* fall through */
      default:
        /* Hit when the user breaks out of the dialog with the escape key
         * or otherwise destroys the dialog window without a proper response */
        /* nothing to do */
        break;
  }
  gtk_widget_destroy (dialog);

  /* Switch back to the page we were on if it wasn't the one being closed */
  g_return_val_if_fail (keep_page != NULL, result);
  if (keep_page != page) {
    s_page_goto (w_current->toplevel, keep_page);
    gschem_toplevel_page_changed (w_current);
  }
  return result;
}
Exemple #4
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 */
static void pagesel_callback_selection_changed (GtkTreeSelection *selection,
        gpointer user_data)
{
    GtkTreeModel *model;
    GtkTreeIter iter;
    Pagesel *pagesel = (Pagesel*)user_data;
    GSCHEM_TOPLEVEL *w_current;
    PAGE *page;

    if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
        return;
    }

    w_current = GSCHEM_DIALOG (pagesel)->w_current;
    gtk_tree_model_get (model, &iter,
                        COLUMN_PAGE, &page,
                        -1);

    /* temp */
    s_page_goto (w_current->toplevel, page);
    i_set_filename (w_current, w_current->toplevel->page_current->page_filename);
    x_scrollbars_update (w_current);
    o_invalidate_all (w_current);

    /* We would like to use the following call, but since it calls
     * x_pagesel_update() it would cause an infinite loop.
     */
    /*  x_window_set_current_page (toplevel, page); */

}
Exemple #5
0
/*! \brief Completes initialitation of the widget after realization.
 *  \par Function Description
 *  This function terminates the initialization of preview's GSCHEM_TOPLEVEL
 *  and TOPLEVEL environments after the widget has been realized.
 *
 *  It creates a preview page in the TOPLEVEL environment.
 *
 *  \param [in] widget    The preview widget.
 *  \param [in] user_data Unused user data.
 */
static void
preview_callback_realize (GtkWidget *widget,
                          gpointer user_data)
{
  Preview *preview = PREVIEW (widget);
  GSCHEM_TOPLEVEL *preview_w_current = preview->preview_w_current;
  TOPLEVEL *preview_toplevel = preview_w_current->toplevel;
  PAGE *preview_page;

  preview_w_current->window = preview_w_current->drawing_area->window;
  gtk_widget_grab_focus (preview_w_current->drawing_area);

  preview_toplevel->width  = preview_w_current->drawing_area->allocation.width;
  preview_toplevel->height = preview_w_current->drawing_area->allocation.height;
  preview_w_current->win_width  = preview_toplevel->width;
  preview_w_current->win_height = preview_toplevel->height;

  preview_w_current->drawable = preview_w_current->window;

  x_window_setup_gc (preview_w_current);

  preview_page = s_page_new (preview_toplevel, "unknown");
  s_page_goto (preview_toplevel, preview_page);

  a_zoom_extents(preview_w_current,
                 s_page_objects (preview_page),
                 A_PAN_DONT_REDRAW);

  o_invalidate_all (preview_w_current);

}
Exemple #6
0
/*! \brief Updates the preview widget.
 *  \par Function Description
 *  This function update the preview: if the preview is active and a
 *  filename has been given, it opens the file and display
 *  it. Otherwise it display a blank page.
 *
 *  \param [in] preview The preview widget.
 */
static void
preview_update (Preview *preview)
{
  GSCHEM_TOPLEVEL *preview_w_current = preview->preview_w_current;
  TOPLEVEL *preview_toplevel = preview_w_current->toplevel;
  int left, top, right, bottom;
  int width, height;

  if (preview_toplevel->page_current == NULL) {
    return;
  }
  
  /* delete old preview, create new page */
  /* it would be better to just resets current page - Fix me */
  s_page_delete (preview_toplevel, preview_toplevel->page_current);
  s_page_goto (preview_toplevel, s_page_new (preview_toplevel, "preview"));
  
  if (preview->active) {
    g_assert ((preview->filename == NULL) || (preview->buffer == NULL));
    if (preview->filename != NULL) {
      /* open up file in current page */
      f_open_flags (preview_toplevel, preview_toplevel->page_current,
                    preview->filename,
                    F_OPEN_RC | F_OPEN_RESTORE_CWD, NULL);
      /* test value returned by f_open... - Fix me */
      /* we should display something if there an error occured - Fix me */
    }
    if (preview->buffer != NULL) {

      /* Load the data buffer */
      s_page_append_list (preview_toplevel, preview_toplevel->page_current,
                          o_read_buffer (preview_toplevel,
                                         NULL, preview->buffer, -1,
                                         _("Preview Buffer")));
    }
  }

  if (world_get_object_glist_bounds (preview_toplevel,
                                     s_page_objects (preview_toplevel->page_current),
                                     &left, &top,
                                     &right, &bottom)) {
    /* Clamp the canvas size to the extents of the page being previewed */
    width = right - left;
    height = bottom - top;
    preview_toplevel->init_left   = left  - ((double)width * OVER_ZOOM_FACTOR);
    preview_toplevel->init_right  = right + ((double)width * OVER_ZOOM_FACTOR);
    preview_toplevel->init_top    = top    - ((double)height * OVER_ZOOM_FACTOR);
    preview_toplevel->init_bottom = bottom + ((double)height * OVER_ZOOM_FACTOR);
  }

  /* display current page (possibly empty) */
  a_zoom_extents (preview_w_current,
                  s_page_objects (preview_toplevel->page_current),
                  A_PAN_DONT_REDRAW);
  o_invalidate_all (preview_w_current);
  
}
Exemple #7
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;
}
Exemple #8
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_save, *p_current;
  gint status = 0;

  /* save current page */
  p_save = toplevel->page_current;

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

    p_current = (PAGE *)iter->data;

    /* make p_current the current page of toplevel */
    s_page_goto (toplevel, p_current);

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

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

  }

  /* restore current page */
  if (p_save != NULL) 
  {
     s_page_goto (toplevel, p_save);
  }

  return status;
}
Exemple #9
0
/*! \brief Changes the current page.
 *  \par Function Description
 *  This function displays the specified page <B>page</B> in the
 *  window attached to <B>toplevel</B>.
 *
 *  It changes the <B>toplevel</B>'s current page to <B>page</B>,
 *  draws it and updates the user interface.
 *
 *  <B>page</B> has to be in the list of PAGEs attached to <B>toplevel</B>.
 *
 *  \param [in] w_current The toplevel environment.
 *  \param [in] page      The page to become current page.
 */
void
x_window_set_current_page (GSCHEM_TOPLEVEL *w_current, PAGE *page)
{
  TOPLEVEL *toplevel = w_current->toplevel;

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

  o_redraw_cleanstates (w_current);

  s_page_goto (toplevel, page);

  i_update_menus (w_current);
  i_set_filename (w_current, page->page_filename);

  x_pagesel_update (w_current);
  x_multiattrib_update (w_current);

  x_manual_resize (w_current);
  x_hscrollbar_update (w_current);
  x_vscrollbar_update (w_current);

  o_invalidate_all (w_current);
}
Exemple #10
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;
}
Exemple #11
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);
}
Exemple #12
0
/*! \brief Do autosave on all pages that are marked.
 *  \par Function Description
 *  Looks for pages with the do_autosave_backup flag activated and
 *  autosaves them.
 *
 *  \param [in] w_current  The GSCHEM_TOPLEVEL object to search for autosave's.
 */
void o_autosave_backups(GSCHEM_TOPLEVEL *w_current)
{
  TOPLEVEL *toplevel = w_current->toplevel;
  GList *iter;
  PAGE *p_save, *p_current;
  gchar *backup_filename;
  gchar *real_filename;
  gchar *only_filename;
  gchar *dirname;
  mode_t saved_umask;
  mode_t mask;
  struct stat st;

  /* save current page */
  p_save = toplevel->page_current;

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

    p_current = (PAGE *)iter->data;

    if (p_current->do_autosave_backup == 0) {
      continue;
    }
    if (p_current->ops_since_last_backup != 0) {
      /* make p_current the current page of toplevel */
      s_page_goto (toplevel, p_current);

      /* Get the real filename and file permissions */
      real_filename = follow_symlinks (p_current->page_filename, NULL);

      if (real_filename == NULL) {
        s_log_message (_("o_autosave_backups: Can't get the real filename of %s."), p_current->page_filename);
      } else {
        /* Get the directory in which the real filename lives */
        dirname = g_path_get_dirname (real_filename);
        only_filename = g_path_get_basename(real_filename);

        backup_filename = g_strdup_printf("%s%c"AUTOSAVE_BACKUP_FILENAME_STRING,
                                          dirname, G_DIR_SEPARATOR, only_filename);

        /* If there is not an existing file with that name, compute the
         * permissions and uid/gid that we will use for the newly-created file.
         */

        if (stat (real_filename, &st) != 0) {
#if defined(HAVE_GETUID) && defined(HAVE_GETGID)
            struct stat dir_st;
            int result;
#endif

            /* Use default permissions */
            saved_umask = umask(0);
            st.st_mode = 0666 & ~saved_umask;
            umask(saved_umask);
#if defined(HAVE_GETUID) && defined(HAVE_GETGID)
            st.st_uid = getuid ();

            result = stat (dirname, &dir_st);

            if (result == 0 && (dir_st.st_mode & S_ISGID))
              st.st_gid = dir_st.st_gid;
            else
              st.st_gid = getgid ();
#endif
          }
        g_free (dirname);
        g_free (only_filename);
        g_free (real_filename);

        /* Make the backup file writable before saving a new one */
        if ( g_file_test (backup_filename, G_FILE_TEST_EXISTS) &&
             (! g_file_test (backup_filename, G_FILE_TEST_IS_DIR))) {
          saved_umask = umask(0);
          if (chmod(backup_filename, (S_IWRITE|S_IWGRP|S_IWOTH) &
                    ((~saved_umask) & 0777)) != 0) {
            s_log_message (_("Could NOT set previous backup file [%s] read-write\n"),
                           backup_filename);
          }
          umask(saved_umask);
        }

        if (o_save (toplevel,
                    s_page_objects (toplevel->page_current),
                    backup_filename, NULL)) {

          p_current->ops_since_last_backup = 0;
                p_current->do_autosave_backup = 0;

          /* Make the backup file readonly so a 'rm *' command will ask
             the user before deleting it */
          saved_umask = umask(0);
          mask = (S_IWRITE|S_IWGRP|S_IEXEC|S_IXGRP|S_IXOTH);
          mask = (~mask)&0777;
          mask &= ((~saved_umask) & 0777);
          if (chmod(backup_filename,mask) != 0) {
            s_log_message (_("Could NOT set backup file [%s] readonly\n"),
                           backup_filename);
          }
          umask(saved_umask);
        } else {
          s_log_message (_("Could NOT save backup file [%s]\n"),
                         backup_filename);
        }
        g_free (backup_filename);
      }
    }
  }
  /* restore current page */
  s_page_goto (toplevel, p_save);
}
Exemple #13
0
void main_prog(void *closure, int argc, char *argv[])
{
    int i;
    int argv_index;
    char *cwd;
    gchar *str;
    gchar *filename;

    TOPLEVEL *pr_current;

    /* set default output filename */
    output_filename = g_strdup("output.net");

    argv_index = parse_commandline(argc, argv);
    cwd = g_get_current_dir();

    scm_set_program_arguments (argc, argv, NULL);

    /* this is a kludge to make sure that spice mode gets set */
    /*  Hacked by SDB to allow spice netlisters of arbitrary name
     *        as long as they begin with "spice".  For example, this spice
     *  netlister is valid: "spice-sdb".
     */
    if (guile_proc) {
        if (strncmp(guile_proc, "spice", 5) == 0) {
            netlist_mode = SPICE;
        }
    }

    libgeda_init();

    /* create log file right away */
    /* even if logging is enabled */
    s_log_init ("gnetlist");

    s_log_message("gEDA/gnetlist version %s%s.%s\n", PREPEND_VERSION_STRING,
                  PACKAGE_DOTTED_VERSION, PACKAGE_DATE_VERSION);
    s_log_message
        ("gEDA/gnetlist comes with ABSOLUTELY NO WARRANTY; see COPYING for more details.\n");
    s_log_message
        ("This is free software, and you are welcome to redistribute it under certain\n");
    s_log_message
        ("conditions; please see the COPYING file for more details.\n\n");

#if defined(__MINGW32__) && defined(DEBUG)
    fprintf(stderr, "This is the MINGW32 port.\n\n");
#endif

    /* register guile (scheme) functions */
    g_register_funcs();

    pr_current = s_toplevel_new ();

    /* Evaluate Scheme expressions that need to be run before rc files
     * are loaded. */
    scm_eval (pre_rc_list, scm_current_module ());

    g_rc_parse (pr_current, argv[0], "gnetlistrc", rc_filename);
    /* immediately setup user params */
    i_vars_set (pr_current);

    s_rename_init();

    if(list_backends) {
      gnetlist_backends(pr_current);
      exit (0);
    }

    /* Evaluate the first set of Scheme expressions before we load any
     * schematic files */
    scm_eval (pre_backend_list, scm_current_module ());

    i = argv_index;
    while (argv[i] != NULL) {
      GError *err = NULL;

      if (g_path_is_absolute(argv[i])) {
        /* Path is already absolute so no need to do any concat of cwd */
        filename = g_strdup (argv[i]);
      } else {
        filename = g_build_filename (cwd, argv[i], NULL);
      }

      if (!quiet_mode) {
        s_log_message ("Loading schematic [%s]\n", filename);
        printf ("Loading schematic [%s]\n", filename);
      }

      s_page_goto (pr_current, s_page_new (pr_current, filename));

      if (!f_open (pr_current, pr_current->page_current, filename, &err)) {
        g_warning ("%s\n", err->message);
        fprintf (stderr, "%s\n", err->message);
        g_error_free (err);
      }

      /* collect input filenames for backend use */
      input_files = g_slist_append(input_files, argv[i]);

      i++;
      g_free (filename);
    }

    /* Change back to the directory where we started.  This is done */
    /* since gnetlist is a command line utility and will deposit its output */
    /* in the current directory.  Having the output go to a different */
    /* directory will confuse the user (confused me, at first). */
    if (chdir (cwd)) {
      /* Error occured with chdir */
#warning FIME: What do we do?
    }
    /* free(cwd); - Defered; see below */

    if (argv[argv_index] == NULL) {
        fprintf (stderr, "ERROR: No schematics files specified for processing.\n");
        fprintf (stderr, "\nRun `%s --help' for more information.\n", argv[0]);
        exit (1);
    }

    g_set_project_current(pr_current);
#if DEBUG
    s_page_print_all(pr_current);
#endif

    /* Load basic gnetlist functions */
    scm_primitive_load_path (scm_from_utf8_string ("gnetlist.scm"));

    if (guile_proc) {
      SCM s_backend_path;

      /* Search for backend scm file in load path */
      str = g_strdup_printf("gnet-%s.scm", guile_proc);
      s_backend_path = scm_sys_search_load_path (scm_from_locale_string (str));
      g_free (str);

      /* If it couldn't be found, fail. */
      if (scm_is_false (s_backend_path)) {
        fprintf (stderr, "ERROR: Could not find backend `%s' in load path.\n",
                 guile_proc);
        fprintf (stderr,
                 "\nRun `%s --list-backends' for a full list of available backends.\n",
                 argv[0]);
        exit (1);
      }

      /* Load backend code. */
      scm_primitive_load (s_backend_path);

      /* Evaluate second set of Scheme expressions. */
      scm_eval (post_backend_list, scm_current_module ());
    }

    s_traverse_init();
    s_traverse_start(pr_current);

    /* Change back to the directory where we started AGAIN.  This is done */
    /* because the s_traverse functions can change the Current Working Directory. */
    if (chdir (cwd)) {
      /* Error occured with chdir */
#warning FIXME: What do we do?
    }
    g_free(cwd);

    /* Run post-traverse code. */
    scm_primitive_load_path (scm_from_utf8_string ("gnetlist-post.scm"));

    if (guile_proc) {
        /* check size here hack */
        str = g_strdup_printf ("(%s \"%s\")", guile_proc, output_filename);
        scm_c_eval_string (str);
        g_free (str);
        /* gh_eval_str_with_stack_saving_handler (input_str); */
    } else if (interactive_mode) {
        scm_c_eval_string ("(set-repl-prompt! \"gnetlist> \")");
        scm_shell (0, NULL);
    } else {
        fprintf(stderr,
                "You gave neither backend to execute nor interactive mode!\n");
    }

    gnetlist_quit();
}
Exemple #14
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;
}
/*! \brief Asks for confirmation before closing a window.
 *  \par Function Description
 *  This function asks the user to confirm its closing order for
 *  the given window.
 *
 *  The user is given the possibility to save the pages that currently
 *  have unsaved changes, if any.
 *
 *  It returns TRUE if the user really accepts the close of the
 *  window. Otherwise the user has somehow cancelled and the window
 *  must not be closed.
 *
 *  \param [in] w_current The toplevel environment.
 *  \returns TRUE if the window can be closed, FALSE otherwise.
 */
gboolean
x_dialog_close_window (GschemToplevel *w_current)
{
  TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
  GList *iter;
  GtkWidget *dialog;
  PAGE *p_current;
  PAGE *keep_page;
  GList *unsaved_pages, *p_unsaved;
  gboolean ret = FALSE;

  keep_page = toplevel->page_current;

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

    p_current = (PAGE*)iter->data;

    if (p_current->CHANGED) {
      unsaved_pages = g_list_append (unsaved_pages, (gpointer)p_current);
    }
  }

  if (unsaved_pages == NULL) {
    /* no page with unsaved changes, close window */
    return TRUE;
  }

  dialog = GTK_WIDGET (g_object_new (TYPE_CLOSE_CONFIRMATION_DIALOG,
                                     "unsaved-pages", unsaved_pages,
                                     NULL));

  gtk_window_set_transient_for (GTK_WINDOW (dialog),
                                GTK_WINDOW (w_current->main_window));

  g_list_free (unsaved_pages);
  switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
      case GTK_RESPONSE_NO:
        /* action selected: close without saving */
        /* discard changes, ok to close window */
        ret = TRUE;
        break;

      case GTK_RESPONSE_YES:
        /* action selected: save */
        g_object_get (dialog,
                      "selected-pages", &unsaved_pages,
                      NULL);
        for (p_unsaved = unsaved_pages, ret = TRUE;
             p_unsaved != NULL;
             p_unsaved = g_list_next (p_unsaved)) {
          p_current = (PAGE*)p_unsaved->data;

          s_page_goto (toplevel, p_current);
          gschem_toplevel_page_changed (w_current);

          i_callback_file_save(w_current, 0, NULL);
          /* if user cancelled previous, do not close window */
          ret &= !p_current->CHANGED;
        }
        g_list_free (unsaved_pages);
        break;

      case GTK_RESPONSE_CANCEL:
        /* action selected: cancel */
        /* fall through */
      default:
        /* Hit when the user breaks out of the dialog with the escape key
         * or otherwise destroys the dialog window without a proper response */
        ret = FALSE;
        break;
  }
  gtk_widget_destroy (dialog);

  /* Switch back to the page we were on */
  g_return_val_if_fail (keep_page != NULL, ret);
  s_page_goto (toplevel, keep_page);
  gschem_toplevel_page_changed (w_current);

  return ret;
}
Exemple #16
0
/*! \brief delete a page and it's contents
 *  \par Function Description
 *  Deletes a single page <B>page</B> from <B>toplevel</B>'s list of pages.
 *
 *  See #s_page_delete_list() to delete all pages of a <B>toplevel</B>
 *
 *  If the current page of toplevel is given as parameter <B>page</B>,
 *  the function sets the field <B>page_current</B> of the TOPLEVEL
 *  struct to NULL.
 */
void s_page_delete (TOPLEVEL *toplevel, PAGE *page)
{
  PAGE *tmp;
  gchar *backup_filename;
  gchar *real_filename;

  /* We need to temporarily make the page being deleted current because
   * various functions called below (some indirectly) assume they are
   * deleting objects from the current page.
   *
   * These functions are known to include:
   *   s_delete_object ()
   */

  /* save page_current and switch to page */
  if (page == toplevel->page_current) {
    tmp = NULL;
  } else {
    tmp = toplevel->page_current;
    s_page_goto (toplevel, page);
  }

  /* Get the real filename and file permissions */
  real_filename = follow_symlinks (page->page_filename, NULL);
  
  if (real_filename == NULL) {
    s_log_message (_("s_page_delete: Can't get the real filename of %s."),
                   page->page_filename);
  }
  else {
    backup_filename = f_get_autosave_filename (real_filename);

    /* Delete the backup file */
    if ( (g_file_test (backup_filename, G_FILE_TEST_EXISTS)) && 
	 (!g_file_test(backup_filename, G_FILE_TEST_IS_DIR)) )
    {
      if (unlink(backup_filename) != 0) {
	s_log_message(_("s_page_delete: Unable to delete backup file %s."),
                      backup_filename);
      }
    }
    g_free (backup_filename);
  }
  g_free(real_filename);

  /* Free the selection object */
  g_object_unref( page->selection_list );

  /* then delete objects of page */
  s_page_delete_objects (toplevel, page);

  /* Free the objects in the place list. */
  s_delete_object_glist (toplevel, page->place_list);
  page->place_list = NULL;

  /*  This removes all objects from the list of connectible objects
   *  of the given \a page. */
  if (g_list_length (page->connectible_list) != 0) {
    fprintf (stderr,
            "OOPS! page->connectible_list had something in it when it was freed!\n");
    fprintf (stderr, "Length: %d\n", g_list_length (page->connectible_list));
  }

  g_list_free (page->connectible_list);
  page->connectible_list = NULL;

  /* free current page undo structs */
  s_undo_free_all (toplevel, page); 

  /* ouch, deal with parents going away and the children still around */
  page->up = -2;
  g_free (page->page_filename);

  geda_list_remove( toplevel->pages, page );

  s_weakref_notify (page, page->weak_refs);

  g_free (page);

  /* restore page_current */
  if (tmp != NULL) {
    s_page_goto (toplevel, tmp);
  } else {
    /* page was page_current */
    s_toplevel_set_page_current (toplevel, NULL);
    /* page_current must be updated by calling function */
  }

}
Exemple #17
0
void 
main_prog(void *closure, int argc, char *argv[])
{
  int i;
  int argv_index;
  int exit_status;
  char *cwd;

  TOPLEVEL *pr_current;
  
  argv_index = parse_commandline(argc, argv);
  cwd = g_get_current_dir();

  libgeda_init();

  /* create log file right away */
  /* even if logging is enabled */
  x_log_update_func = s_log_update;
  s_log_init ("symcheck");

  logging_dest=STDOUT_TTY;

#if defined(__MINGW32__) && defined(DEBUG)
  fprintf(stderr, "This is the MINGW32 port.\n");
#endif  

  logging_dest=-1; /* don't output to the screen for now */
  
  /* register guile (scheme) functions */
  g_register_funcs();

  pr_current = s_toplevel_new ();
  g_rc_parse (pr_current, argv[0], "gsymcheckrc", rc_filename);

  i_vars_set(pr_current);
  
  i = argv_index;
  while (argv[i] != NULL) {

    gchar *filename;
    GError *err = NULL;

    if (g_path_is_absolute(argv[i]))
    {
      /* Path is already absolute so no need to do any concat of cwd */
      filename = g_strdup (argv[i]);
    } else {
      filename = g_build_filename (cwd, argv[i], NULL);
    }

    s_page_goto (pr_current,
                 s_page_new (pr_current, filename));

    if (!f_open (pr_current,
                 pr_current->page_current,
                 s_page_get_filename (pr_current->page_current),
                 &err)) {
      /* Not being able to load a file is apparently a fatal error */
      logging_dest = STDOUT_TTY;
      g_warning ("%s\n", err->message);
      g_error_free (err);
      exit(2);
    } else {
      g_message (_("Loaded file [%1$s]\n"), filename);
    }
    i++;
    g_free (filename);
  }

  if (argv[argv_index] == NULL) {
    fprintf(stderr, _("\nERROR! You must specify at least one filename\n\n"));
    usage(argv[0]);
  }

  g_free(cwd);

  logging_dest=STDOUT_TTY;

#if DEBUG 
  s_page_print_all(pr_current);
#endif
  
  if (!quiet_mode) s_log_message("\n");

  exit_status = s_check_all(pr_current);

  s_page_delete_list(pr_current);
  gsymcheck_quit();

  exit(exit_status);
}
Exemple #18
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] w_current 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;
  GError *err = NULL;

  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, toplevel->page_current, filename, &err);
  if (ret != 1) {
    log_msg   = _("Could NOT save page [%s]\n");
    state_msg = _("Error while trying to save");

    GtkWidget *dialog;

    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 save file"));
    gtk_dialog_run (GTK_DIALOG (dialog));
    gtk_widget_destroy (dialog);
    g_clear_error (&err);
  } 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;

    /* add to recent file list */
    gtk_recent_manager_add_item (recent_manager, g_filename_to_uri(filename, NULL, NULL));
  }

  /* 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;
}
Exemple #19
0
/*! \brief delete a page and it's contents
 *  \par Function Description
 *  Deletes a single page <B>page</B> from <B>toplevel</B>'s list of pages.
 *
 *  See #s_page_delete_list() to delete all pages of a <B>toplevel</B>
 *
 *  If the current page of toplevel is given as parameter <B>page</B>,
 *  the function sets the field <B>page_current</B> of the TOPLEVEL
 *  struct to NULL.
 */
void s_page_delete (TOPLEVEL *toplevel, PAGE *page)
{
  PAGE *tmp;
  gchar *backup_filename;
  gchar *real_filename;

  /* We need to temporarily make the page being deleted current because
   * various functions called below (some indirectly) assume they are
   * deleting objects from the current page.
   *
   * These functions are known to include:
   *   s_delete_object ()
   */

  /* save page_current and switch to page */
  if (page == toplevel->page_current) {
    tmp = NULL;
  } else {
    tmp = toplevel->page_current;
    s_page_goto (toplevel, page);
  }

  /* Get the real filename and file permissions */
  real_filename = follow_symlinks (page->page_filename, NULL);
  
  if (real_filename == NULL) {
    s_log_message (_("s_page_delete: Can't get the real filename of %s."),
                   page->page_filename);
  }
  else {
    backup_filename = f_get_autosave_filename (real_filename);

    /* Delete the backup file */
    if ( (g_file_test (backup_filename, G_FILE_TEST_EXISTS)) && 
	 (!g_file_test(backup_filename, G_FILE_TEST_IS_DIR)) )
    {
      if (unlink(backup_filename) != 0) {
	s_log_message(_("s_page_delete: Unable to delete backup file %s."),
                      backup_filename);
      }
    }
    g_free (backup_filename);
  }
  g_free(real_filename);

  /* Free the selection object */
  g_object_unref( page->selection_list );

  /* then delete objects of page */
  s_page_delete_objects (toplevel, page);

  /* Free the objects in the place list. */
  s_delete_object_glist (toplevel, page->place_list);
  page->place_list = NULL;

#if DEBUG
  printf("Freeing page: %s\n", page->page_filename);
  s_tile_print(toplevel);
#endif
  s_tile_free_all (page);

  s_stretch_destroy_all (page->stretch_list);

  /* free current page undo structs */
  s_undo_free_all (toplevel, page); 

  /* ouch, deal with parents going away and the children still around */
  page->up = -2;
  g_free (page->page_filename);

  geda_list_remove( toplevel->pages, page );

#if DEBUG
  s_tile_print (toplevel);
#endif

  g_free (page);

  /* restore page_current */
  if (tmp != NULL) {
    s_page_goto (toplevel, tmp);
  } else {
    /* page was page_current */
    toplevel->page_current = NULL;
    /* page_current must be updated by calling function */
  }

}
Exemple #20
0
void
s_hierarchy_traverse(TOPLEVEL * pr_current, OBJECT * o_current,
		     NETLIST * netlist)
{
    char *attrib;
    int page_control=-1;
    PAGE *p_current;
    PAGE *child_page;
    int count = 0;
    int pcount = 0;
    int looking_inside = FALSE;
    int loaded_flag = FALSE;
    char *current_filename;
    int graphical=FALSE;

    attrib = o_attrib_search_attached_attribs_by_name (o_current, "source", 0);

    /* 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 DEBUG
	printf("going to look inside now\n");
#endif
    }

    graphical = s_hierarchy_graphical_search(o_current, count);
    if (graphical) {
	/* Do not bother traversing the hierarchy if the symbol has an */
	/* graphical attribute attached to it. */
	if (attrib) {
	    g_free(attrib);
 	    attrib = NULL;
	}
    }

    while (attrib) {

	/* look for source=filename,filename, ... */
	pcount = 0;
	current_filename = u_basic_breakup_string(attrib, ',', pcount);

	/* loop over all filenames */
	while (current_filename != NULL) {

	    s_log_message(_("Going to traverse source [%1$s]"),
			  current_filename);

	    /* guts here */
	    /* guts for a single filename */
	    p_current = pr_current->page_current;
#if DEBUG
	    printf("Going down %s\n", current_filename);
#endif
            GError *err = NULL;
	    child_page =
		s_hierarchy_down_schematic_single(pr_current,
						  current_filename,
						  pr_current->page_current,
						  page_control,
                                                  HIERARCHY_FORCE_LOAD,
                                                  &err);

	    if (child_page == NULL) {
              g_warning (_("Failed to load subcircuit '%1$s': %2$s\n"),
                         current_filename, err->message);
              fprintf(stderr, _("ERROR: Failed to load subcircuit '%1$s': %2$s\n"),
                      current_filename, err->message);
              g_error_free (err);
              exit (2);

	    } else {
              page_control = child_page->page_control;
              s_page_goto (pr_current, child_page);

		loaded_flag = TRUE;

		verbose_print("v\n");
		verbose_reset_index();

		netlist->composite_component = TRUE;
		/* can't do the following, don't know why... HACK TODO */
		/*netlist->hierarchy_tag = u_basic_strdup (netlist->component_uref);*/
		s_traverse_sheet (pr_current,
		                  s_page_objects (pr_current->page_current),
		                  netlist->component_uref);

		verbose_print("^");
	    }

	    pr_current->page_current = p_current;

	    g_free(current_filename);
	    pcount++;
	    current_filename = u_basic_breakup_string(attrib, ',', pcount);
	}

	g_free(attrib);

	g_free(current_filename);

	count++;

	/* continue looking outside first */
	if (!looking_inside) {
	    attrib =
		o_attrib_search_attached_attribs_by_name (o_current, "source",
		                                          count);
	}

	/* okay we were looking outside and didn't */
	/* find anything, so now we need to look */
	/* inside the symbol */
	if (!looking_inside && attrib == NULL && !loaded_flag) {
	    looking_inside = TRUE;
#if DEBUG
	    printf("switching to go to look inside\n");
#endif
	}

	if (looking_inside) {
#if DEBUG
	    printf("looking inside\n");
#endif
	    attrib =
	        o_attrib_search_inherited_attribs_by_name (o_current,
	                                                   "source", count);
	}

        graphical = s_hierarchy_graphical_search(o_current, count);
        if (graphical) {
	  /* Do not bother looking further in the hierarchy if the symbol */
          /* has an graphical attribute attached to it. */
	  if (attrib) {
	     g_free(attrib);
	     attrib = NULL;
          }
       }
    }
}
Exemple #21
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);
}
Exemple #22
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;
}
Exemple #23
0
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 *  <B>type</B> can be one of the following values:
 *  <DL>
 *    <DT>*</DT><DD>UNDO_ACTION
 *    <DT>*</DT><DD>REDO_ACTION
 *  </DL>
 */
void o_undo_callback(GSCHEM_TOPLEVEL *w_current, int type)
{
  TOPLEVEL *toplevel = w_current->toplevel;
  UNDO *u_current;
  UNDO *u_next;
  UNDO *save_bottom;
  UNDO *save_tos;
  UNDO *save_current;
  int save_logging;
  int find_prev_data=FALSE;

  char *save_filename;

  if (w_current->undo_control == FALSE) {
    s_log_message(_("Undo/Redo disabled in rc file\n"));
    return;
  }

  if (toplevel->page_current->undo_current == NULL) {
    return;
  }

  if (type == UNDO_ACTION) {
    u_current = toplevel->page_current->undo_current->prev;
  } else {
    u_current = toplevel->page_current->undo_current->next;
  }

  u_next = toplevel->page_current->undo_current;

  if (u_current == NULL) {
    return;
  }

  if (u_next->type == UNDO_ALL && u_current->type == UNDO_VIEWPORT_ONLY) {
#if DEBUG
    printf("Type: %d\n", u_current->type);
    printf("Current is an undo all, next is viewport only!\n");
#endif
    find_prev_data = TRUE;

    if (w_current->undo_type == UNDO_DISK) {
      u_current->filename = o_undo_find_prev_filename(u_current);
    } else {
      u_current->object_list = o_undo_find_prev_object_head (u_current);
    }
  }

  /* save filename */
  save_filename = g_strdup (toplevel->page_current->page_filename);

  /* save structure so it's not nuked */
  save_bottom = toplevel->page_current->undo_bottom;
  save_tos = toplevel->page_current->undo_tos;
  save_current = toplevel->page_current->undo_current;
  toplevel->page_current->undo_bottom = NULL;
  toplevel->page_current->undo_tos = NULL;
  toplevel->page_current->undo_current = NULL;

  if (w_current->undo_type == UNDO_DISK && u_current->filename) {
    PAGE *p_new;
    s_page_delete (toplevel, toplevel->page_current);
    p_new = s_page_new(toplevel, u_current->filename);
    s_page_goto (toplevel, p_new);
  } else if (w_current->undo_type == UNDO_MEMORY && u_current->object_list) {
    PAGE *p_new;
    s_page_delete (toplevel, toplevel->page_current);
    p_new = s_page_new (toplevel, save_filename);
    s_page_goto (toplevel, p_new);
  }

  /* temporarily disable logging */
  save_logging = do_logging;
  do_logging = FALSE;

  if (w_current->undo_type == UNDO_DISK && u_current->filename) {

    f_open(toplevel, toplevel->page_current, u_current->filename, NULL);

    x_manual_resize(w_current);
    toplevel->page_current->page_control = u_current->page_control;
    toplevel->page_current->up = u_current->up;
    toplevel->page_current->CHANGED=1;

  } else if (w_current->undo_type == UNDO_MEMORY && u_current->object_list) {

    s_page_delete_objects (toplevel, toplevel->page_current);

    s_page_append_list (toplevel, toplevel->page_current,
                        o_glist_copy_all (toplevel, u_current->object_list,
                                          NULL));

    x_manual_resize(w_current);
    toplevel->page_current->page_control = u_current->page_control;
    toplevel->page_current->up = u_current->up;
    toplevel->page_current->CHANGED=1;
  }

  /* do misc setups */
  set_window(toplevel, toplevel->page_current,
             u_current->left, u_current->right,
             u_current->top, u_current->bottom);
  x_hscrollbar_update(w_current);
  x_vscrollbar_update(w_current);

  /* restore logging */
  do_logging = save_logging;

  /* set filename right */
  g_free(toplevel->page_current->page_filename);
  toplevel->page_current->page_filename = save_filename;

  /* final redraw */
  x_pagesel_update (w_current);
  x_multiattrib_update (w_current);

  /* Let the caller to decide if redraw or not */
  o_invalidate_all (w_current);
  i_update_menus(w_current);

  /* restore saved undo structures */
  toplevel->page_current->undo_bottom = save_bottom;
  toplevel->page_current->undo_tos = save_tos;
  toplevel->page_current->undo_current = save_current;

  if (type == UNDO_ACTION) {
    if (toplevel->page_current->undo_current) {
      toplevel->page_current->undo_current =
          toplevel->page_current->undo_current->prev;
      if (toplevel->page_current->undo_current == NULL) {
        toplevel->page_current->undo_current =
            toplevel->page_current->undo_bottom;
      }
    }
  } else { /* type is REDO_ACTION */
    if (toplevel->page_current->undo_current) {
      toplevel->page_current->undo_current =
          toplevel->page_current->undo_current->next;
      if (toplevel->page_current->undo_current == NULL) {
        toplevel->page_current->undo_current =
            toplevel->page_current->undo_tos;
      }
    }
  }

  /* don't have to free data here since filename, object_list are */
  /* just pointers to the real data (lower in the stack) */
  if (find_prev_data) {
    u_current->filename = NULL;
    u_current->object_list = NULL;
  }

#if DEBUG
  printf("\n\n---Undo----\n");
  s_undo_print_all(toplevel->page_current->undo_bottom);
  printf("TOS: %s\n", toplevel->page_current->undo_tos->filename);
  printf("CURRENT: %s\n", toplevel->page_current->undo_current->filename);
  printf("----\n");
#endif
}
Exemple #24
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;
}
Exemple #25
0
void 
main_prog(void *closure, int argc, char *argv[])
{
  int i;
  int argv_index;
  int exit_status;
  char *cwd;

  char *logfile;
  
  TOPLEVEL *pr_current;
  
  argv_index = parse_commandline(argc, argv);
  cwd = g_get_current_dir();

  libgeda_init();

  /* create log file right away */
  /* even if logging is enabled */
  logfile = g_build_filename (cwd, "gsymcheck.log", NULL);
  x_log_update_func = s_log_update;
  s_log_init (logfile);
  g_free (logfile);

  logging_dest=STDOUT_TTY;
  if (!quiet_mode)
  {
    s_log_message(
                  "gEDA/gsymcheck version %s%s.%s\n", PREPEND_VERSION_STRING,
                  DOTTED_VERSION, DATE_VERSION);
    s_log_message(
                  "gEDA/symcheck comes with ABSOLUTELY NO WARRANTY; see COPYING for more details.\n");
    s_log_message(
                  "This is free software, and you are welcome to redistribute it under certain\n");
    s_log_message(
                  "conditions; please see the COPYING file for more details.\n\n"); 
  }

#ifdef __MINGW32__
  fprintf(stderr, "This is the MINGW32 port.\n");
#endif  

  logging_dest=-1; /* don't output to the screen for now */
  
  /* register guile (scheme) functions */
  g_register_funcs();

  pr_current = s_toplevel_new ();
  g_rc_parse(pr_current, "gsymcheckrc", rc_filename);

  i_vars_set(pr_current);
  
  i = argv_index;
  while (argv[i] != NULL) {

    gchar *filename;
    GError *err = NULL;

    if (g_path_is_absolute(argv[i]))
    {
      /* Path is already absolute so no need to do any concat of cwd */
      filename = g_strdup (argv[i]);
    } else {
      filename = g_build_filename (cwd, argv[i], NULL);
    }

    s_page_goto (pr_current,
                 s_page_new (pr_current, filename));

    if (!f_open (pr_current,
                 pr_current->page_current->page_filename,
                 &err)) {
      /* Not being able to load a file is apparently a fatal error */
      logging_dest = STDOUT_TTY;
      g_warning ("%s\n", err->message);
      g_error_free (err);
      exit(2);
    } else {
      g_message ("Loaded file [%s]\n", filename);
    }
    i++;
    g_free (filename);
  }

  if (argv[argv_index] == NULL) {
    fprintf(stderr, "\nERROR! You must specify at least one filename\n\n");
    usage(argv[0]);
  }

  g_free(cwd);

  logging_dest=STDOUT_TTY;

#if DEBUG 
  s_page_print_all(pr_current);
#endif
  
  if (!quiet_mode) s_log_message("\n");

  exit_status = s_check_all(pr_current);

  s_page_delete_list(pr_current);
  gsymcheck_quit();

  exit(exit_status);
}