コード例 #1
0
ファイル: o_undo.c プロジェクト: eivindkv/geda-gaf
/*! \todo Finish function documentation!!!
 *  \brief
 *  \par Function Description
 *
 *  
 *  <B>flag</B> can be one of the following values:
 *  <DL>
 *    <DT>*</DT><DD>UNDO_ALL
 *    <DT>*</DT><DD>UNDO_VIEWPORT_ONLY
 *  </DL>
 */
void o_undo_savestate(GSCHEM_TOPLEVEL *w_current, int flag)
{
  TOPLEVEL *toplevel = w_current->toplevel;
  char *filename = NULL;
  GList *object_list = NULL;
  int levels;
  UNDO *u_current;
  UNDO *u_current_next;

  /* save autosave backups if necessary */
  o_autosave_backups(w_current);

  if (w_current->undo_control == FALSE) {
    return;
  }

  if (flag == UNDO_ALL) {

    /* Increment the number of operations since last backup if 
       auto-save is enabled */
    if (toplevel->auto_save_interval != 0) {
      toplevel->page_current->ops_since_last_backup++;
    }

    /* HACK */
    /* Before we save the undo state, consolidate nets as necessary */

    /* This is where the net consolidation call would have been
     * triggered before it was removed from o_save_buffer().
     */
    if (toplevel->net_consolidate == TRUE)
      o_net_consolidate (toplevel, toplevel->page_current);
  }

  if (w_current->undo_type == UNDO_DISK && flag == UNDO_ALL) {

    filename = g_strdup_printf("%s%cgschem.save%d_%d.sch",
                               tmp_path, G_DIR_SEPARATOR,
                               prog_pid, undo_file_index++);

    /* Changed from f_save to o_save when adding backup copy creation. */
    /* f_save manages the creaton of backup copies. 
       This way, f_save is called only when saving a file, and not when
       saving an undo backup copy */
    o_save (toplevel, s_page_objects (toplevel->page_current), filename, NULL);

  } else if (w_current->undo_type == UNDO_MEMORY && flag == UNDO_ALL) {
    object_list = o_glist_copy_all (toplevel,
                                    s_page_objects (toplevel->page_current),
                                    object_list);
  }

  /* Clear Anything above current */
  if (toplevel->page_current->undo_current) {
    s_undo_remove_rest(toplevel,
                       toplevel->page_current->undo_current->next);
    toplevel->page_current->undo_current->next = NULL;
  } else { /* undo current is NULL */
    s_undo_remove_rest(toplevel,
                       toplevel->page_current->undo_bottom);
    toplevel->page_current->undo_bottom = NULL;
  }

  toplevel->page_current->undo_tos = toplevel->page_current->undo_current;

  toplevel->page_current->undo_tos =
  s_undo_add(toplevel->page_current->undo_tos,
             flag, filename, object_list,
             toplevel->page_current->left,
             toplevel->page_current->top,
             toplevel->page_current->right,
             toplevel->page_current->bottom,
             toplevel->page_current->page_control,
             toplevel->page_current->up);

  toplevel->page_current->undo_current =
      toplevel->page_current->undo_tos;

  if (toplevel->page_current->undo_bottom == NULL) {
    toplevel->page_current->undo_bottom =
        toplevel->page_current->undo_tos;
  }

#if DEBUG
  printf("\n\n---Undo----\n");
  s_undo_print_all(toplevel->page_current->undo_bottom);
  printf("BOTTOM: %s\n", toplevel->page_current->undo_bottom->filename);
  printf("TOS: %s\n", toplevel->page_current->undo_tos->filename);
  printf("CURRENT: %s\n", toplevel->page_current->undo_current->filename);
  printf("----\n");
#endif

  g_free(filename);

  /* Now go through and see if we need to free/remove some undo levels */ 
  /* so we stay within the limits */

  /* only check history every 10 undo savestates */
  if (undo_file_index % 10) {
    return;
  }

  levels = s_undo_levels(toplevel->page_current->undo_bottom);

#if DEBUG
  printf("levels: %d\n", levels);
#endif

  if (levels >= w_current->undo_levels + UNDO_PADDING) {
    levels = levels - w_current->undo_levels;

#if DEBUG
    printf("Trimming: %d levels\n", levels);
#endif

    u_current = toplevel->page_current->undo_bottom;
    while(u_current && levels > 0) {
      u_current_next = u_current->next;

      if (u_current->filename) {
#if DEBUG
        printf("Freeing: %s\n", u_current->filename);
#endif
        unlink(u_current->filename);
        g_free(u_current->filename);
      }

      if (u_current->object_list) {
        s_delete_object_glist (toplevel, u_current->object_list);
        u_current->object_list = NULL;
      }

      u_current->next = NULL;
      u_current->prev = NULL;
      g_free(u_current);

      u_current = u_current_next;
      levels--;
    }

    /* Because we use a pad you are always garanteed to never */
    /* exhaust the list */
    u_current->prev = NULL;
    toplevel->page_current->undo_bottom = u_current;

#if DEBUG
    printf("New current is: %s\n", u_current->filename);
#endif
  }

#if DEBUG
  printf("\n\n---Undo----\n");
  s_undo_print_all(toplevel->page_current->undo_bottom);
  printf("BOTTOM: %s\n", toplevel->page_current->undo_bottom->filename);
  printf("TOS: %s\n", toplevel->page_current->undo_tos->filename);
  printf("CURRENT: %s\n", toplevel->page_current->undo_current->filename);
  printf("----\n");
#endif

}
コード例 #2
0
ファイル: f_basic.c プロジェクト: jgriessen/geda-gaf
/*! \brief Opens the schematic file with fine-grained control over behaviour.
 *  \par Function Description
 *  Opens the schematic file and carries out a number of actions
 *  depending on the \a flags set.  If #F_OPEN_RC is set, executes
 *  configuration files found in the target directory.  If
 *  #F_OPEN_CHECK_BACKUP is set, warns user if a backup is found for
 *  the file being loaded, and possibly prompts user for whether to
 *  load the backup instead.  If #F_OPEN_RESTORE_CWD is set, does not
 *  change the working directory to that of the file being loaded.
 *
 *  \param [in,out] toplevel  The TOPLEVEL object to load the schematic into.
 *  \param [in]     filename   A character string containing the file name
 *                             to open.
 *  \param [in]     flags      Combination of #FOpenFlags values.
 *  \param [in,out] err  #GError structure for error reporting, or
 *                       NULL to disable error reporting
 *
 *  \return 0 on failure, 1 on success.
 */
int f_open_flags(TOPLEVEL *toplevel, const gchar *filename,
                 const gint flags, GError **err)
{
  int opened=FALSE;
  char *full_filename = NULL;
  char *full_rcfilename = NULL;
  char *file_directory = NULL;
  char *saved_cwd = NULL;
  char *backup_filename = NULL;
  char load_backup_file = 0;
  GError *tmp_err = NULL;

  /* has the head been freed yet? */
  /* probably not hack PAGE */

  set_window(toplevel, toplevel->page_current,
             toplevel->init_left, toplevel->init_right,
             toplevel->init_top,  toplevel->init_bottom);


  /* Cache the cwd so we can restore it later. */
  if (flags & F_OPEN_RESTORE_CWD) {
    saved_cwd = g_get_current_dir();
  }

  /* get full, absolute path to file */
  full_filename = f_normalize_filename (filename, &tmp_err);
  if (full_filename == NULL) {
    g_set_error (err, G_FILE_ERROR, tmp_err->code,
                 _("Cannot find file %s: %s"),
                 filename, tmp_err->message);
    g_error_free(tmp_err);
    return 0;
  }

  /* write full, absolute filename into page_current->page_filename */
  g_free(toplevel->page_current->page_filename);
  toplevel->page_current->page_filename = g_strdup(full_filename);

  /* Before we open the page, let's load the corresponding gafrc. */
  /* First cd into file's directory. */
  file_directory = g_dirname (full_filename);

  if (file_directory) { 
    if (chdir (file_directory)) {
      /* Error occurred with chdir */
#warning FIXME: What do we do?
    }
  }

  /* Now open RC and process file */
  if (flags & F_OPEN_RC) {
    full_rcfilename = g_build_filename (file_directory, "gafrc", NULL);
    g_rc_parse_specified_rc(toplevel, full_rcfilename);
  }

  g_free (file_directory);

  if (flags & F_OPEN_CHECK_BACKUP) {
    /* Check if there is a newer autosave backup file */
    GString *message;
    gboolean active_backup = f_has_active_autosave (full_filename, &tmp_err);
    backup_filename = f_get_autosave_filename (full_filename);

    if (tmp_err != NULL) g_warning ("%s\n", tmp_err->message);
    if (active_backup) {
      message = g_string_new ("");
      g_string_append_printf(message, _("\nWARNING: Found an autosave backup file:\n  %s.\n\n"), backup_filename);
      if (tmp_err != NULL) {
        g_string_append(message, _("I could not guess if it is newer, so you have to do it manually.\n"));
      } else {
        g_string_append(message, _("The backup copy is newer than the schematic, so it seems you should load it instead of the original file.\n"));
      }
      g_string_append (message, _("Gschem usually makes backup copies automatically, and this situation happens when it crashed or it was forced to exit abruptly.\n"));
      if (toplevel->page_current->load_newer_backup_func == NULL) {
        g_warning ("%s", message->str);
        g_warning (_("\nRun gschem and correct the situation.\n\n"));
      } else {
        /* Ask the user if load the backup or the original file */
        if (toplevel->page_current->load_newer_backup_func
            (toplevel, message)) {
          /* Load the backup file */
          load_backup_file = 1;
        }
      }
      g_string_free (message, TRUE);
    }
    if (tmp_err != NULL) g_error_free (tmp_err);
  }

  /* Now that we have set the current directory and read
   * the RC file, it's time to read in the file. */
  if (load_backup_file == 1) {
    /* Load the backup file */
    s_page_append_list (toplevel->page_current,
                        o_read (toplevel, NULL, backup_filename, &tmp_err));
  } else {
    /* Load the original file */
    s_page_append_list (toplevel->page_current,
                        o_read (toplevel, NULL, full_filename, &tmp_err));
  }

  if (tmp_err == NULL)
    opened = TRUE;
  else
    g_propagate_error (err, tmp_err);

  /* make sure you init net_consolide to false (default) in all */
  /* programs */
  if (toplevel->net_consolidate == TRUE) {
    o_net_consolidate(toplevel);
  }

  if (load_backup_file == 0) {
    /* If it's not the backup file */
    toplevel->page_current->CHANGED=0; /* added 4/7/98 */
  } else {
    /* We are loading the backup file, so gschem should ask
       the user if save it or not when closing the page. */
    toplevel->page_current->CHANGED=1;
  }

  g_free(full_filename);
  g_free(full_rcfilename);
  g_free (backup_filename);

  /* Reset the directory to the value it had when f_open was
   * called. */
  if (flags & F_OPEN_RESTORE_CWD) {
    if (chdir (saved_cwd)) {
      /* Error occurred with chdir */
#warning FIXME: What do we do?
    }
    g_free(saved_cwd);
  }

  return opened;
}