/*! \todo Finish function documentation!!! * \brief * \par Function Description * * \note * Test function which only prints the name of a page and its number. */ gint s_hierarchy_print_page (PAGE *p_current, void * data) { printf("pagefilename: %s pageid: %d\n", s_page_get_filename (p_current), p_current->pid); return 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 Update tree model of <B>pagesel</B>'s treeview. * \par Function Description * Updates the tree model of <B>pagesel</B>\'s treeview. * * Right now, each time it is called, it rebuilds all the model from the * list of pages passed in. * It is a recursive function to populate the tree store * * \param [in] model GtkTreeModel to update. * \param [in] parent GtkTreeIter pointer to tree root. * \param [in] pages GedaPageList of pages for this toplevel. * \param [in] page The PAGE object to update tree model from. */ static void add_page (GtkTreeModel *model, GtkTreeIter *parent, GedaPageList *pages, PAGE *page) { GtkTreeIter iter; PAGE *p_current; GList *p_iter; /* add the page to the store */ gtk_tree_store_append (GTK_TREE_STORE (model), &iter, parent); gtk_tree_store_set (GTK_TREE_STORE (model), &iter, COLUMN_PAGE, page, COLUMN_NAME, s_page_get_filename (page), COLUMN_CHANGED, page->CHANGED, -1); /* search a page that has a up field == p_current->pid */ for ( p_iter = geda_list_get_glist( pages ); p_iter != NULL; p_iter = g_list_next( p_iter ) ) { p_current = (PAGE *)p_iter->data; if (p_current->up == page->pid) { add_page (model, &iter, pages, p_current); } } }
/*! \brief places object in the store so the user can see them * * \param [in] state * \param [in] objects the list of objects to put in the store */ static void assign_store (GschemFindTextState *state, GSList *objects) { GSList *object_iter; g_return_if_fail (state != NULL); g_return_if_fail (state->store != NULL); clear_store (state); object_iter = objects; while (object_iter != NULL) { char *basename; OBJECT *object = (OBJECT*) object_iter->data; const char *str; GtkTreeIter tree_iter; object_iter = g_slist_next (object_iter); if (object == NULL) { g_warning ("NULL object encountered"); continue; } if (object->page == NULL) { g_warning ("NULL page encountered"); continue; } if (object->type != OBJ_TEXT) { g_warning ("expecting a text object"); continue; } str = geda_text_object_get_string (object); if (str == NULL) { g_warning ("NULL string encountered"); continue; } s_object_weak_ref (object, (NotifyFunc) object_weakref_cb, state); gtk_list_store_append (state->store, &tree_iter); basename = g_path_get_basename (s_page_get_filename (object->page)); gtk_list_store_set (state->store, &tree_iter, COLUMN_FILENAME, basename, COLUMN_STRING, str, COLUMN_OBJECT, object, -1); g_free (basename); } }
/*! \brief Export a print-style PDF file of the current page. * \par Function Description * Exports the current page as a PDF file to \a filename. The * export is carried out using a normal paper size and margins, as if * printing. * * \param w_current A #GschemToplevel structure. * \param filename The filename for generated PDF. * * \returns TRUE if the operation was successful. */ gboolean x_print_export_pdf_page (GschemToplevel *w_current, const gchar *filename) { PAGE *page; cairo_surface_t *surface; cairo_status_t status; cairo_t *cr; GtkPageSetup *setup; double width, height; EdaConfig *cfg; gboolean is_color; page = w_current->toplevel->page_current; setup = x_print_default_page_setup (w_current->toplevel, page ); width = gtk_page_setup_get_paper_width (setup, GTK_UNIT_POINTS); height = gtk_page_setup_get_paper_height (setup, GTK_UNIT_POINTS); surface = cairo_pdf_surface_create (filename, width, height); cr = cairo_create (surface); cairo_translate (cr, gtk_page_setup_get_left_margin (setup, GTK_UNIT_POINTS), gtk_page_setup_get_top_margin (setup, GTK_UNIT_POINTS)); width = gtk_page_setup_get_page_width (setup, GTK_UNIT_POINTS); height = gtk_page_setup_get_page_height (setup, GTK_UNIT_POINTS); /* Find out if colour printing is enabled */ cfg = eda_config_get_context_for_path (s_page_get_filename (page)); is_color = !eda_config_get_boolean (cfg, CFG_GROUP_PRINTING, CFG_KEY_PRINTING_MONOCHROME, NULL); x_print_draw_page (w_current->toplevel, page, cr, NULL, width, height, is_color, FALSE); cairo_destroy (cr); cairo_surface_finish (surface); status = cairo_surface_status (surface); if (status != CAIRO_STATUS_SUCCESS) { g_warning (_("Failed to write PDF to '%s': %s\n"), filename, cairo_status_to_string (status)); return FALSE; } g_object_unref (setup); cairo_surface_destroy (surface); return TRUE; }
/*! \brief Update the list and status of <B>toplevel</B>'s pages. * \par Function Description * Updates the list and status of <B>toplevel</B>\'s pages if the page * manager dialog is opened. * * \param [in] w_current The GschemToplevel object to update. */ void x_pagesel_update (GschemToplevel *w_current) { if (w_current->pswindow) { g_assert (IS_PAGESEL (w_current->pswindow)); pagesel_update (PAGESEL (w_current->pswindow)); } PAGE *page = gschem_page_view_get_page (gschem_toplevel_get_current_page_view (w_current)); if (page == NULL) { return; } i_set_filename (w_current, s_page_get_filename (page), page->CHANGED ? "* " : ""); }
/*! \brief Create a default page setup for a schematic page. * \par Function Description * Creates and returns a new #GtkPageSetup for \a page, taking into * account the requested \a paper_size_name. If \a paper_size_name is * NULL, the system default paper size is used. The \a orientation may * be LANDSCAPE, PORTRAIT or AUTOLAYOUT. If \a AUTOLAYOUT is chosen, * the page orientation that best fits the page contents is chosen. * * \param toplevel A #TOPLEVEL structure. * \param page The #PAGE to generate a page setup for. * \param paper_size_name The name of the paper size to use. * \param orientation The paper orientation to use. * * \returns A newly-created page setup. */ static GtkPageSetup * x_print_default_page_setup (TOPLEVEL *toplevel, PAGE *page) { GtkPageSetup *setup = gtk_page_setup_new (); GtkPaperSize *papersize; int status, wx_min, wy_min, wx_max, wy_max; EdaConfig *cfg; gchar *paper, *orientation; /* Get configuration values */ cfg = eda_config_get_context_for_path (s_page_get_filename (page)); paper = eda_config_get_string (cfg, CFG_GROUP_PRINTING, CFG_KEY_PRINTING_PAPER, NULL); orientation = eda_config_get_string (cfg, CFG_GROUP_PRINTING, CFG_KEY_PRINTING_ORIENTATION, NULL); /* If the paper size is valid, set it up with default margins. */ papersize = gtk_paper_size_new (paper); if (papersize != NULL) { gtk_page_setup_set_paper_size_and_default_margins (setup, papersize); } if (g_strcmp0 (orientation, "landscape") == 0) { gtk_page_setup_set_orientation (setup, GTK_PAGE_ORIENTATION_LANDSCAPE); } else if (g_strcmp0 (orientation, "portrait") == 0) { gtk_page_setup_set_orientation (setup, GTK_PAGE_ORIENTATION_PORTRAIT); } else if (orientation == NULL || g_strcmp0 (orientation, "auto") == 0) { /* Automatically choose the orientation that fits best */ status = world_get_object_glist_bounds (toplevel, s_page_objects (page), &wx_min, &wy_min, &wx_max, &wy_max); if (!status || (wx_max - wx_min) > (wy_max - wy_min)) { /* Default to landscape */ gtk_page_setup_set_orientation (setup, GTK_PAGE_ORIENTATION_LANDSCAPE); } else { gtk_page_setup_set_orientation (setup, GTK_PAGE_ORIENTATION_PORTRAIT); } } g_free (paper); g_free (orientation); return setup; }
/*! \brief Load a subpage * * \par Function Description * Implements s_hierarchy_down_schematic(), but without changing variables * related to the UI. * * - Ensures a duplicate page is not loaded * - Does not change the current page * - Does not modify the most recent "up" page * * \param [in] page * \param [in] filename * \param [out] error * \return A pointer to the subpage or NULL if an error occured. */ PAGE* s_hierarchy_load_subpage (PAGE *page, const char *filename, GError **error) { char *string; PAGE *subpage = NULL; g_return_val_if_fail (filename != NULL, NULL); g_return_val_if_fail (page != NULL, NULL); SCM string_s = scm_call_1 (scm_c_public_ref ("geda library", "get-source-library-file"), scm_from_utf8_string (filename)); if (scm_is_false (string_s)) { g_set_error (error, EDA_ERROR, EDA_ERROR_NOLIB, _("Schematic not found in source library.")); } else { string = scm_to_utf8_string (string_s); gchar *normalized = f_normalize_filename (string, error); subpage = s_page_search (page->toplevel, normalized); if (subpage == NULL) { int success; subpage = s_page_new (page->toplevel, string); success = f_open (page->toplevel, subpage, s_page_get_filename (subpage), error); if (success) { subpage->page_control = ++page_control_counter; } else { s_page_delete (page->toplevel, subpage); subpage = NULL; } } g_free (normalized); } return subpage; }
/*! \brief Returns the name to use for the given page in the model. * \par Function Description * This function determines the text to be used to identify a * specific page from the model of pages with unsaved changes. * * If <B>piter</B> is NULL, the name for the first page of the model * is returned. Otherwise, it returns the name for the page defined * by the pointed iterator. * * The returned value must be freed by caller. * * \param [in] model The tree model. * \param [in] piter A pointer on a GtkTreeIter of model or NULL. * \returns The name for the page. */ static gchar* get_page_name (GtkTreeModel *model, GtkTreeIter *piter) { GtkTreeIter iter; PAGE *page; g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL); if (piter == NULL) { gtk_tree_model_get_iter_first (model, &iter); } else { iter = *piter; } gtk_tree_model_get (model, &iter, COLUMN_PAGE, &page, -1); g_assert (page != NULL); return g_path_get_basename (s_page_get_filename (page)); }
/*! Drawing callback for use with GtkPrintOperation. */ static void draw_page__print_operation (GtkPrintOperation *print, GtkPrintContext *context, gint page_nr, gpointer user_data) { GschemToplevel *w_current = (GschemToplevel *) user_data; PAGE *page; cairo_t *cr; PangoContext *pc; double width, height; EdaConfig *cfg; gboolean is_color; /* Find the page data */ g_return_if_fail (page_nr != 1); page = w_current->toplevel->page_current; g_return_if_fail (page != NULL); /* Get cairo & pango contexts */ cr = gtk_print_context_get_cairo_context (context); pc = gtk_print_context_create_pango_context (context); width = gtk_print_context_get_width (context); height = gtk_print_context_get_height (context); /* Find out if colour printing is enabled */ cfg = eda_config_get_context_for_path (s_page_get_filename (page)); is_color = !eda_config_get_boolean (cfg, CFG_GROUP_PRINTING, CFG_KEY_PRINTING_MONOCHROME, NULL); x_print_draw_page (w_current->toplevel, page, cr, pc, width, height, is_color, FALSE); /* Clean up */ g_object_unref (pc); }
/*! * \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; }
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); }