示例#1
0
/*! \brief Closes a page.
 *  \par Function Description
 *  This function closes the page <B>page</B> of toplevel
 *  <B>toplevel</B>.
 *
 *  If necessary, the current page of <B>toplevel</B> is changed to
 *  the next valid page or to a new untitled page.
 *
 *  \param [in] w_current The toplevel environment.
 *  \param [in] page      The page to close.
 */
void
x_window_close_page (GSCHEM_TOPLEVEL *w_current, PAGE *page)
{
  TOPLEVEL *toplevel = w_current->toplevel;
  PAGE *new_current = NULL;
  GList *iter;

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

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

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

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

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

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

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

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

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

    /* change to new_current and update display */
    x_window_set_current_page (w_current, new_current);
  }
}
示例#2
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;
}
示例#3
0
/*! \brief Opens a file chooser for opening one or more schematics.
 *  \par Function Description
 *  This function opens a file chooser dialog and wait for the user to
 *  select at least one file to load as <B>w_current</B>'s new pages.
 *
 *  The function updates the user interface.
 *
 *  At the end of the function, the w_current->toplevel's current page
 *  is set to the page of the last loaded page.
 *
 *  \param [in] w_current The GSCHEM_TOPLEVEL environment.
 */
void
x_fileselect_open(GSCHEM_TOPLEVEL *w_current)
{
  PAGE *page = NULL;
  GtkWidget *dialog;

  dialog = gtk_file_chooser_dialog_new (_("Open..."),
                                        GTK_WINDOW(w_current->main_window),
                                        GTK_FILE_CHOOSER_ACTION_OPEN,
                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                        GTK_STOCK_OPEN,   GTK_RESPONSE_ACCEPT,
                                        NULL);

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

  x_fileselect_add_preview (GTK_FILE_CHOOSER (dialog));  
  g_object_set (dialog,
                /* GtkFileChooser */
                "select-multiple", TRUE,
                NULL);
  /* add file filters to dialog */
  x_fileselect_setup_filechooser_filters (GTK_FILE_CHOOSER (dialog));
  gtk_widget_show (dialog);
  if (gtk_dialog_run ((GtkDialog*)dialog) == GTK_RESPONSE_ACCEPT) {
    GSList *tmp, *filenames =
      gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (dialog));

    /* open each file */ 
    for (tmp = filenames; tmp != NULL;tmp = g_slist_next (tmp)) {
      page = x_window_open_page (w_current, (gchar*)tmp->data);
    }
    /* Switch to the last page opened */
    if ( page != NULL )
      x_window_set_current_page (w_current, page);

    /* free the list of filenames */
    g_slist_foreach (filenames, (GFunc)g_free, NULL);
    g_slist_free (filenames);
  }
  gtk_widget_destroy (dialog);

}
示例#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);

  /* Since setting the current page may call x_pagesel_update(), which
   * might change the current page selection, make sure we do nothing
   * if the newly-selected page is already the current page. */
  if (page == w_current->toplevel->page_current) return;
  x_window_set_current_page (w_current, page);
}
示例#5
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;
}
示例#6
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);
}
示例#7
0
文件: gschem.c 项目: fvila/geda-gaf
/*! \brief Main Scheme(GUILE) program function.
 *  \par Function Description
 *  This function is the main program called from scm_boot_guile.
 *  It handles initializing all libraries and gSchem variables
 *  and passes control to the gtk main loop.
 */
void main_prog(void *closure, int argc, char *argv[])
{
  int i;
  char *cwd = NULL;
  GSCHEM_TOPLEVEL *w_current = NULL;
  char *input_str = NULL;
  int argv_index;
  int first_page = 1;
  char *filename;
  SCM scm_tmp;

#ifdef HAVE_GTHREAD
  /* Gschem isn't threaded, but some of GTK's file chooser
   * backends uses threading so we need to call g_thread_init().
   * GLib requires threading be initialised before any other GLib
   * functions are called. Do it now if its not already setup.  */
  if (!g_thread_supported ()) g_thread_init (NULL);
#endif

#if ENABLE_NLS
  /* this should be equivalent to setlocale (LC_ALL, "") */
  gtk_set_locale();

  /* This must be the same for all locales */
  setlocale(LC_NUMERIC, "C");

  /* Disable gtk's ability to set the locale. */ 
  /* If gtk is allowed to set the locale, then it will override the     */
  /* setlocale for LC_NUMERIC (which is important for proper PS output. */
  /* This may look funny here, given we make a call to gtk_set_locale() */
  /* above.  I don't know yet, if this is really the right thing to do. */
  gtk_disable_setlocale(); 

#endif

  gtk_init(&argc, &argv);

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

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

  s_log_message(
                _("gEDA/gschem version %s%s.%s\n"), PREPEND_VERSION_STRING,
                PACKAGE_DOTTED_VERSION, PACKAGE_DATE_VERSION);
  s_log_message(
                _("gEDA/gschem 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"));
#endif  

#if DEBUG
  fprintf(stderr, _("Current locale settings: %s\n"), setlocale(LC_ALL, NULL));
#endif

  /* init global buffers */
  o_buffer_init();

  /* register guile (scheme) functions */
  g_register_funcs();
  g_init_window ();
  g_init_select ();
  g_init_hook ();
  g_init_attrib ();
  g_init_keys ();
  g_init_util ();

  /* initialise color map (need to do this before reading rc files */
  x_color_init ();

  o_undo_init(); 

  if (s_path_sys_data () == NULL) {
    const gchar *message = 
      _("You must set the GEDADATA environment variable!\n\n"
        "gschem cannot locate its data files. You must set the GEDADATA\n"
        "environment variable to point to the correct location.\n");
    GtkWidget* error_diag =
      gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR,
                              GTK_BUTTONS_OK,
                              "%s", message);
    gtk_dialog_run (GTK_DIALOG (error_diag));
    g_error ("%s", message);
  }

  /* Allocate w_current */
  w_current = gschem_toplevel_new ();

  /* Connect hooks that run for each s_toplevel_new() first */
  s_toplevel_append_new_hook ((NewToplevelFunc) add_libgeda_toplevel_hooks,
                              w_current);

  w_current->toplevel = s_toplevel_new ();

  w_current->toplevel->load_newer_backup_func = x_fileselect_load_backup;
  w_current->toplevel->load_newer_backup_data = w_current;

  o_text_set_rendered_bounds_func (w_current->toplevel,
                                   o_text_get_rendered_bounds, w_current);

  /* Damage notifications should invalidate the object on screen */
  o_add_change_notify (w_current->toplevel,
                       (ChangeNotifyFunc) o_invalidate,
                       (ChangeNotifyFunc) o_invalidate, w_current);

  scm_dynwind_begin (0);
  g_dynwind_window (w_current);

  /* Run pre-load Scheme expressions */
  g_scm_eval_protected (s_pre_load_expr, scm_current_module ());

  /* By this point, libgeda should have setup the Guile load path, so
   * we can take advantage of that.  */
  scm_tmp = scm_sys_search_load_path (scm_from_utf8_string ("gschem.scm"));
  if (scm_is_false (scm_tmp)) {
    s_log_message (_("Couldn't find init scm file [%s]\n"), "gschem.scm");
  }
  input_str = scm_to_utf8_string (scm_tmp);
  if (g_read_file(w_current->toplevel, input_str, NULL)) {
    s_log_message(_("Read init scm file [%s]\n"), input_str);
  } else {
    /*! \todo These two messages are the same. Should be
     * integrated. */
    s_log_message(_("Failed to read init scm file [%s]\n"),
                  input_str);
  }
  free (input_str); /* M'allocated by scm_to_utf8_string() */
  scm_remember_upto_here_1 (scm_tmp);

  /* Now read in RC files. */
  g_rc_parse_gtkrc();
  x_rc_parse_gschem (w_current, rc_filename);

  /* Set default icon */
  x_window_set_default_icon();

  /* At end, complete set up of window. */
  x_color_allocate();
  x_window_setup (w_current);

#ifdef HAVE_LIBSTROKE
  x_stroke_init ();
#endif /* HAVE_LIBSTROKE */

  for (i = argv_index; i < argc; i++) {

    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 ( first_page )
      first_page = 0;

    /*
     * SDB notes:  at this point the filename might be unnormalized, like
     * /path/to/foo/../bar/baz.sch.  Bad filenames will be normalized in
     * f_open (called by x_window_open_page). This works for Linux and MINGW32.
     */
    x_window_open_page(w_current, filename);
    g_free (filename);
  }

  g_free(cwd);

  /* If no page has been loaded (wasn't specified in the command line.) */
  /* Then create an untitled page */
  if ( first_page ) {
    x_window_open_page( w_current, NULL );
  }

  /* Update the window to show the current page */
  x_window_set_current_page( w_current, w_current->toplevel->page_current );


#if DEBUG
  scm_c_eval_string ("(display \"hello guile\n\")");
#endif

  /* Run post-load expressions */
  g_scm_eval_protected (s_post_load_expr, scm_current_module ());

  /* open up log window on startup */
  if (w_current->log_window == MAP_ON_STARTUP) {
    x_log_open ();
  }

  /* if there were any symbols which had major changes, put up an error */
  /* dialog box */
  major_changed_dialog(w_current);

  scm_dynwind_end ();

  /* enter main loop */
  gtk_main();
}