示例#1
0
/* We assume that data is actually a char**. The way we return results
 * from this function is to malloc a fresh string, and store it in
 * this pointer. It is the caller's responsibility to do something
 * smart with this freshly allocated storage. the caller can determine
 * whether there was an error by initializing the char* passed in to
 * NULL. If there is an error, the char string will not be NULL on
 * return. */
static SCM
gfec_catcher(void *data, SCM tag, SCM throw_args)
{
    SCM func;
    SCM result;
    const char *msg = NULL;

    func = scm_c_eval_string("gnc:error->string");
    if (scm_is_procedure(func))
    {
        result = scm_call_2(func, tag, throw_args);
        if (scm_is_string(result))
        {
            char * str;

            scm_dynwind_begin (0); 
            str = scm_to_locale_string (result);
            msg = g_strdup (str);
            scm_dynwind_free (str); 
            scm_dynwind_end (); 
        }
    }

    if (msg == NULL)
    {
        msg = "Error running guile function.";
    }

    *(char**)data = strdup(msg);

    return SCM_UNDEFINED;
}
示例#2
0
static SCM
scscm_call_2_body (void *argsp)
{
  SCM *args = argsp;

  return scm_call_2 (args[0], args[1], args[2]);
}
示例#3
0
文件: gfec.c 项目: Mechtilde/gnucash
SCM
gfec_apply(SCM proc, SCM arglist, gfec_error_handler error_handler)
{
    SCM result = SCM_UNDEFINED;
    SCM func = scm_c_eval_string("gnc:apply-with-error-handling");
    if (scm_is_procedure(func))
    {
        char *err_msg = NULL;
        SCM call_result, error;
        call_result = scm_call_2 (func, proc, arglist);

        error = scm_list_ref (call_result, scm_from_uint (1));
        if (scm_is_true (error))
            err_msg = gnc_scm_to_utf8_string (error);
        else
            result = scm_list_ref (call_result, scm_from_uint (0));

        if (err_msg != NULL)
        {
            if (error_handler)
                error_handler (err_msg);

            free(err_msg);
        }
    }

    return result;
}
static void
gnc_column_view_edit_close_cb(GNCOptionWin * win, gpointer user_data)
{
    gnc_column_view_edit * r = user_data;
    SCM set_editor = scm_c_eval_string("gnc:report-set-editor-widget!");

    scm_call_2(set_editor, r->view, SCM_BOOL_F);
    gnc_column_view_edit_destroy(r);
}
示例#5
0
/********************************************************************
 * update_report_list
 *
 * this procedure does the real work of displaying a sorted list of
 * available custom reports
 ********************************************************************/
static void
update_report_list(GtkListStore *store, CustomReportDialog *crd)
{
    SCM get_rpt_guids = scm_c_eval_string("gnc:custom-report-template-guids");
    SCM template_menu_name = scm_c_eval_string("gnc:report-template-menu-name/report-guid");
    SCM rpt_guids;
    int i;
    GtkTreeIter iter;
    GtkTreeModel *model = GTK_TREE_MODEL (store);
    gboolean valid_iter;

    gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), COL_NAME, GTK_SORT_ASCENDING);

    crd->reportlist = scm_call_0(get_rpt_guids);
    rpt_guids = crd->reportlist;

    /* Empty current liststore */
    valid_iter = gtk_tree_model_get_iter_first (model, &iter);
    while (valid_iter)
    {
        GValue value = { 0, };
        GncGUID *row_guid;
        g_value_init ( &value, G_TYPE_POINTER);
        gtk_tree_model_get_value (model, &iter, COL_NUM, &value);
        row_guid = (GncGUID *) g_value_get_pointer (&value);
        guid_free (row_guid);
        g_value_unset (&value);
        valid_iter = gtk_tree_model_iter_next (model, &iter);
    }
    gtk_list_store_clear(store);

    if (scm_is_list(rpt_guids))
    {
        /* for all the report guids in the list, store them, with a reference,
        	 in the gtkliststore */
        for (i = 0; !scm_is_null(rpt_guids); i++)
        {
            GncGUID *guid = guid_malloc ();
            gchar *guid_str = scm_to_utf8_string (SCM_CAR(rpt_guids));
            gchar *name = gnc_scm_to_utf8_string (scm_call_2(template_menu_name, SCM_CAR(rpt_guids), SCM_BOOL_F));

            if (string_to_guid (guid_str, guid))
            {
                gtk_list_store_append(store, &iter);
                gtk_list_store_set(store, &iter,
                                   COL_NAME, name,
                                   COL_NUM, guid,
                                   -1);
            }
            g_free (name);
            g_free (guid_str);

            rpt_guids = SCM_CDR(rpt_guids);
        }
    }
}
static void
gnc_column_view_edit_apply_cb(GNCOptionWin * w, gpointer user_data)
{
    SCM  dirty_report = scm_c_eval_string("gnc:report-set-dirty?!");
    gnc_column_view_edit * win = user_data;

    if (!win) return;
    gnc_option_db_commit(win->odb);
    scm_call_2(dirty_report, win->view, SCM_BOOL_T);
}
示例#7
0
static void
inner_main_add_price_quotes(void *closure, int argc, char **argv)
{
    SCM mod, add_quotes, scm_book, scm_result = SCM_BOOL_F;
    QofSession *session = NULL;

    scm_c_eval_string("(debug-set! stack 200000)");

    mod = scm_c_resolve_module("gnucash price-quotes");
    scm_set_current_module(mod);

    load_gnucash_modules();

    qof_event_suspend();
    scm_c_eval_string("(gnc:price-quotes-install-sources)");

    if (!gnc_quote_source_fq_installed())
    {
        g_print("%s", _("No quotes retrieved. Finance::Quote isn't "
                        "installed properly.\n"));
        goto fail;
    }

    add_quotes = scm_c_eval_string("gnc:book-add-quotes");
    session = gnc_get_current_session();
    if (!session) goto fail;

    qof_session_begin(session, add_quotes_file, FALSE, FALSE);
    if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;

    qof_session_load(session, NULL);
    if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;

    scm_book = gnc_book_to_scm(qof_session_get_book(session));
    scm_result = scm_call_2(add_quotes, SCM_BOOL_F, scm_book);

    qof_session_save(session, NULL);
    if (qof_session_get_error(session) != ERR_BACKEND_NO_ERR) goto fail;

    qof_session_destroy(session);
    if (!scm_is_true(scm_result))
    {
        g_warning("Failed to add quotes to %s.", add_quotes_file);
        goto fail;
    }

    qof_event_resume();
    gnc_shutdown(0);
    return;
fail:
    if (session && qof_session_get_error(session) != ERR_BACKEND_NO_ERR)
        g_warning("Session Error: %s", qof_session_get_error_message(session));
    qof_event_resume();
    gnc_shutdown(1);
}
示例#8
0
/********************************************************************\
 * gnc_trans_scm_append_split_scm                                   *
 *   append the scheme split onto the scheme transaction            *
 *                                                                  *
 * Args: trans_scm - the scheme transaction                         *
 *       split_scm - the scheme split to append                     *
 * Returns: Nothing                                                 *
\********************************************************************/
void
gnc_trans_scm_append_split_scm(SCM trans_scm, SCM split_scm)
{
    initialize_scm_functions();

    if (!gnc_is_trans_scm(trans_scm))
        return;
    if (!gnc_is_split_scm(split_scm))
        return;

    scm_call_2(setters.trans_scm_append_split_scm, trans_scm, split_scm);
}
示例#9
0
/********************************************************************\
 * gnc_split_scm_set_amount                                         *
 *   set the amount of a scheme split                               *
 *                                                                  *
 * Args: split_scm - the scheme split                               *
 *       amount    - the amount to set                              *
 * Returns: Nothing                                                 *
\********************************************************************/
void
gnc_split_scm_set_amount(SCM split_scm, gnc_numeric amount)
{
    SCM arg;

    initialize_scm_functions();

    if (!gnc_is_split_scm(split_scm))
        return;

    arg = gnc_numeric_to_scm(amount);
    scm_call_2(setters.split_scm_amount, split_scm, arg);
}
示例#10
0
/********************************************************************\
 * gnc_split_scm_set_value                                          *
 *   set the value of a scheme split                                *
 *                                                                  *
 * Args: split_scm - the scheme split                               *
 *       value     - the value to set                               *
 * Returns: Nothing                                                 *
\********************************************************************/
void
gnc_split_scm_set_value(SCM split_scm, gnc_numeric value)
{
    SCM arg;

    initialize_scm_functions();

    if (!gnc_is_split_scm(split_scm))
        return;

    arg = gnc_numeric_to_scm(value);
    scm_call_2(setters.split_scm_value, split_scm, arg);
}
示例#11
0
/********************************************************************\
 * gnc_trans_scm_get_split_scm                                      *
 *   get the indexth scheme split of a scheme transaction.          *
 *                                                                  *
 * Args: trans_scm - the scheme transaction                         *
 *       index     - the index of the split to get                  *
 * Returns: scheme split to get, or SCM_UNDEFINED if none           *
\********************************************************************/
SCM
gnc_trans_scm_get_split_scm(SCM trans_scm, int index)
{
    SCM arg;

    initialize_scm_functions();

    if (!gnc_is_trans_scm(trans_scm))
        return SCM_UNDEFINED;

    arg = scm_from_int (index);

    return scm_call_2(getters.trans_scm_split_scm, trans_scm, arg);
}
示例#12
0
/********************************************************************\
 * gnc_split_scm_set_reconcile_state                                *
 *   set the reconcile state of a scheme split.                     *
 *                                                                  *
 * Args: split_scm       - the scheme split                         *
 *       reconcile_state - the reconcile state to set               *
 * Returns: Nothing                                                 *
\********************************************************************/
void
gnc_split_scm_set_reconcile_state(SCM split_scm, char reconcile_state)
{
    SCM arg;

    initialize_scm_functions();

    if (!gnc_is_split_scm(split_scm))
        return;

    arg = SCM_MAKE_CHAR(reconcile_state);

    scm_call_2(setters.split_scm_reconcile_state, split_scm, arg);
}
示例#13
0
/****************************************************************
 * gnc_ui_qif_account_picker_new_cb
 *
 * This handler is invoked when the user wishes to create a new
 * account.
 ****************************************************************/
void
gnc_ui_qif_account_picker_new_cb(GtkButton * w, gpointer user_data)
{
    QIFAccountPickerDialog * wind = user_data;
    SCM name_setter = scm_c_eval_string("qif-map-entry:set-gnc-name!");
    const gchar *name;
    int response;
    gchar *fullname;
    GtkWidget *dlg, *entry;

    /* Create a dialog to get the new account name. */
    dlg = gtk_message_dialog_new(GTK_WINDOW(wind->dialog),
                                 GTK_DIALOG_DESTROY_WITH_PARENT,
                                 GTK_MESSAGE_QUESTION,
                                 GTK_BUTTONS_OK_CANCEL,
                                 "%s", _("Enter a name for the account"));
    gtk_dialog_set_default_response(GTK_DIALOG(dlg), GTK_RESPONSE_OK);
    entry = gtk_entry_new();
    gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
    gtk_entry_set_max_length(GTK_ENTRY(entry), 250);
    gtk_widget_show(entry);
    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dlg)->vbox), entry);

    /* Run the dialog to get the new account name. */
    response = gtk_dialog_run(GTK_DIALOG(dlg));
    name = gtk_entry_get_text(GTK_ENTRY(entry));

    /* Did the user enter a name and click OK? */
    if (response == GTK_RESPONSE_OK && name && *name)
    {
        /* If an account is selected, this will be a new subaccount. */
        if (wind->selected_name && *(wind->selected_name))
            /* We have the short name; determine the full name. */
            fullname = g_strjoin(gnc_get_account_separator_string(),
                                 wind->selected_name, name, (char *)NULL);
        else
            fullname = g_strdup(name);

        /* Save the full name and update the map entry. */
        g_free(wind->selected_name);
        wind->selected_name = fullname;
        scm_call_2(name_setter, wind->map_entry, scm_from_utf8_string(fullname));
    }
    gtk_widget_destroy(dlg);

    /* Refresh the tree display and give it the focus. */
    build_acct_tree(wind, wind->qif_wind);
    gtk_widget_grab_focus(GTK_WIDGET(wind->treeview));
}
示例#14
0
SCM
scm_make_foreign_object_type (SCM name, SCM slot_names,
                              scm_t_struct_finalize finalizer)
{
  SCM type;

  static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
  scm_i_pthread_once (&once, init_make_fobj_type_var);

  type = scm_call_2 (scm_variable_ref (make_fobj_type_var), name, slot_names);

  if (finalizer)
    SCM_SET_VTABLE_INSTANCE_FINALIZER (type, finalizer);

  return type;
}
示例#15
0
/********************************************************************\
 * gnc_trans_scm_set_num                                            *
 *   set the num of a scheme transaction.                           *
 *                                                                  *
 * Args: trans_scm - the scheme transaction                         *
 *       num       - the num to set                                 *
 * Returns: Nothing                                                 *
\********************************************************************/
void
gnc_trans_scm_set_num(SCM trans_scm, const char *num)
{
    SCM arg;

    initialize_scm_functions();

    if (!gnc_is_trans_scm(trans_scm))
        return;
    if (num == NULL)
        return;

    arg = scm_makfrom0str(num);

    scm_call_2(setters.trans_scm_num, trans_scm, arg);
}
示例#16
0
/********************************************************************\
 * gnc_trans_scm_set_description                                    *
 *   set the description of a scheme transaction.                   *
 *                                                                  *
 * Args: trans_scm   - the scheme transaction                       *
 *       description - the description to set                       *
 * Returns: Nothing                                                 *
\********************************************************************/
void
gnc_trans_scm_set_description(SCM trans_scm, const char *description)
{
    SCM arg;

    initialize_scm_functions();

    if (!gnc_is_trans_scm(trans_scm))
        return;
    if (description == NULL)
        return;

    arg = scm_from_utf8_string(description);

    scm_call_2(setters.trans_scm_description, trans_scm, arg);
}
示例#17
0
/********************************************************************\
 * gnc_trans_scm_set_notes                                          *
 *   set the notes of a scheme transaction.                         *
 *                                                                  *
 * Args: trans_scm - the scheme transaction                         *
 *       notes     - the notes to set                               *
 * Returns: Nothing                                                 *
\********************************************************************/
void
gnc_trans_scm_set_notes(SCM trans_scm, const char *notes)
{
    SCM arg;

    initialize_scm_functions();

    if (!gnc_is_trans_scm(trans_scm))
        return;
    if (notes == NULL)
        return;

    arg = scm_from_utf8_string(notes);

    scm_call_2(setters.trans_scm_notes, trans_scm, arg);
}
示例#18
0
/********************************************************************\
 * gnc_split_scm_set_action                                         *
 *   set the action of a scheme representation of a split.          *
 *                                                                  *
 * Args: split_scm - the scheme split                               *
 *       action    - the action to set                              *
 * Returns: Nothing                                                 *
\********************************************************************/
void
gnc_split_scm_set_action(SCM split_scm, const char *action)
{
    SCM arg;

    initialize_scm_functions();

    if (!gnc_is_split_scm(split_scm))
        return;
    if (action == NULL)
        return;

    arg = scm_from_utf8_string(action);

    scm_call_2(setters.split_scm_action, split_scm, arg);
}
示例#19
0
/********************************************************************\
 * gnc_trans_scm_set_date                                           *
 *   set the date of a scheme transaction.                          *
 *                                                                  *
 * Args: trans_scm - the scheme transaction                         *
 *       ts        - the time to set                                *
 * Returns: Nothing                                                 *
\********************************************************************/
void
gnc_trans_scm_set_date(SCM trans_scm, Timespec *ts)
{
    SCM arg;

    initialize_scm_functions();

    if (!gnc_is_trans_scm(trans_scm))
        return;
    if (ts == NULL)
        return;

    arg = gnc_timespec2timepair(*ts);

    scm_call_2(setters.trans_scm_date, trans_scm, arg);
}
示例#20
0
/********************************************************************\
 * gnc_split_scm_set_memo                                           *
 *   set the memo of a scheme representation of a split.            *
 *                                                                  *
 * Args: split_scm - the scheme split                               *
 *       memo      - the memo to set                                *
 * Returns: Nothing                                                 *
\********************************************************************/
void
gnc_split_scm_set_memo(SCM split_scm, const char *memo)
{
    SCM arg;

    initialize_scm_functions();

    if (!gnc_is_split_scm(split_scm))
        return;
    if (memo == NULL)
        return;

    arg = scm_from_utf8_string(memo);

    scm_call_2(setters.split_scm_memo, split_scm, arg);
}
示例#21
0
/**************************************************************
 * custom_report_run_report
 *
 * this procedure sets up and calls the report on the scheme
 * side. This is what makes the report actually run.
 **************************************************************/
static void
custom_report_edit_report_name (SCM guid,
                                CustomReportDialog *crd,
                                gchar *new_name)
{
    SCM rename_report = scm_c_eval_string("gnc:rename-report");
    SCM new_name_scm = scm_from_utf8_string(new_name);

    if (scm_is_null(guid) || !new_name || (*new_name == '\0'))
        return;

    /* rename the report */
    scm_call_2(rename_report, guid, new_name_scm);
    update_report_list(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(crd->reportview))),
                       crd);

}
示例#22
0
SCM apply_rule (SCM board_smob, SCM rule_func) {
	SCM cell;
	struct board *board;
	int i; 
	int j;

	scm_assert_smob_type(board_tag, board_smob);
	board = (struct board *) SCM_SMOB_DATA(board_smob);

	for (i = 0; i < board->height; i++) {
		for (j = 0; j < board->width; j++) {
			cell = scm_list_ref(scm_list_ref(board->cell_list, scm_from_int(j)), scm_from_int(i));
			scm_call_2(rule_func, cell, get_living_neighbors(board_smob, cell));
		}
	}

	return SCM_UNSPECIFIED;
}
示例#23
0
void
custom_report_name_edited_cb(GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer data)
{
    CustomReportDialog *crd = data;
    SCM guid = get_custom_report_selection(crd, _("Unable to change report configuration name."));
    SCM unique_name_func = scm_c_eval_string("gnc:report-template-has-unique-name?");
    SCM new_name_scm = scm_from_utf8_string(new_text);

    g_object_set(G_OBJECT(crd->namerenderer), "editable", FALSE, NULL);
    if (scm_is_null (guid))
        return;

    if (scm_is_true (scm_call_2 (unique_name_func, guid, new_name_scm)))
        custom_report_edit_report_name (guid, crd, new_text);
    else
        gnc_error_dialog (GTK_WINDOW (crd->dialog), "%s",
                          _("A saved report configuration with this name already exists, please choose another name.") );
}
示例#24
0
/********************************************************************\
 * gnc_trans_scm_get_other_split_scm                                *
 *   get the other scheme split of a scheme transaction.            *
 *                                                                  *
 * Args: trans_scm - the scheme transaction                         *
 *       split_scm - the split not to get                           *
 * Returns: other scheme split, or SCM_UNDEFINED if none            *
\********************************************************************/
SCM
gnc_trans_scm_get_other_split_scm(SCM trans_scm, SCM split_scm)
{
    SCM result;

    initialize_scm_functions();

    if (!gnc_is_trans_scm(trans_scm))
        return SCM_UNDEFINED;
    if (!gnc_is_split_scm(split_scm))
        return SCM_UNDEFINED;

    result = scm_call_2(getters.trans_scm_other_split_scm, trans_scm, split_scm);

    if (!gnc_is_split_scm(result))
        return SCM_UNDEFINED;

    return result;
}
示例#25
0
/********************************************************************\
 * gnc_copy_trans                                                   *
 *   returns a scheme representation of a transaction. If the       *
 *   transaction is NULL, SCM_UNDEFINED is returned.                *
 *                                                                  *
 * Args: trans             - the transaction to copy                *
 *       use_cut_semantics - if TRUE, copy is for a 'cut' operation *
 * Returns: SCM representation of transaction or SCM_UNDEFINED      *
\********************************************************************/
SCM
gnc_copy_trans(Transaction *trans, gboolean use_cut_semantics)
{
    static swig_type_info *trans_type = NULL;
    SCM func;
    SCM arg;

    if (trans == NULL)
        return SCM_UNDEFINED;

    func = scm_c_eval_string("gnc:transaction->transaction-scm");
    if (!scm_is_procedure(func))
        return SCM_UNDEFINED;

    if (!trans_type)
        trans_type = SWIG_TypeQuery("_p_Transaction");

    arg = SWIG_NewPointerObj(trans, trans_type, 0);

    return scm_call_2(func, arg, SCM_BOOL(use_cut_semantics));
}
示例#26
0
/*********************************************************************
 * custom_report_delete
 *
 * this will delete the report, update the reports list and leave the
 * dialog active for additional usage.
 *********************************************************************/
static void
custom_report_delete (SCM guid, CustomReportDialog *crd)
{
    SCM template_menu_name = scm_c_eval_string("gnc:report-template-menu-name/report-guid");
    gchar *report_name;

    if (scm_is_null (guid))
        return;

    report_name = gnc_scm_to_utf8_string(scm_call_2(template_menu_name, guid, SCM_BOOL_F));

    /* we must confirm the user wants to delete their precious custom report! */
    if (gnc_verify_dialog( GTK_WINDOW (crd->dialog), FALSE, _("Are you sure you want to delete %s?"), report_name))
    {
        SCM del_report = scm_c_eval_string("gnc:delete-report");
        scm_call_1(del_report, guid);
        update_report_list(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(crd->reportview))),
                           crd);
    }
    g_free (report_name);
}
示例#27
0
/********************************************************************\
 * gnc_split_scm_set_account                                        *
 *   set the account of a scheme representation of a split.         *
 *                                                                  *
 * Args: split_scm - the scheme split                               *
 *       account   - the account to set                             *
 * Returns: Nothing                                                 *
\********************************************************************/
void
gnc_split_scm_set_account(SCM split_scm, Account *account)
{
    const char *guid_string;
    SCM arg;

    initialize_scm_functions();

    if (!gnc_is_split_scm(split_scm))
        return;
    if (account == NULL)
        return;

    guid_string = guid_to_string(xaccAccountGetGUID(account));
    if (guid_string == NULL)
        return;

    arg = scm_makfrom0str(guid_string);

    scm_call_2(setters.split_scm_account_guid, split_scm, arg);
}
示例#28
0
/********************************************************************\
 * gnc_split_scm_set_account                                        *
 *   set the account of a scheme representation of a split.         *
 *                                                                  *
 * Args: split_scm - the scheme split                               *
 *       account   - the account to set                             *
 * Returns: Nothing                                                 *
\********************************************************************/
void
gnc_split_scm_set_account(SCM split_scm, Account *account)
{
    gchar guid_string[GUID_ENCODING_LENGTH+1];
    SCM arg;

    initialize_scm_functions();

    if (!gnc_is_split_scm(split_scm))
        return;
    if (account == NULL)
        return;

    guid_to_string_buff(xaccAccountGetGUID(account), guid_string);
    if (strlen(guid_string) == 0)
        return;

    arg = scm_from_utf8_string(guid_string);

    scm_call_2(setters.split_scm_account_guid, split_scm, arg);
}
示例#29
0
/********************************************************************\
 * gnc_copy_split                                                   *
 *   returns a scheme representation of a split. If the split is    *
 *   NULL, SCM_UNDEFINED is returned.                               *
 *                                                                  *
 * Args: split             - the split to copy                      *
 *       use_cut_semantics - if TRUE, copy is for a 'cut' operation *
 * Returns: SCM representation of split or SCM_UNDEFINED            *
\********************************************************************/
SCM
gnc_copy_split(Split *split, gboolean use_cut_semantics)
{
    static swig_type_info *split_type = NULL;
    SCM func;
    SCM arg;

    if (split == NULL)
        return SCM_UNDEFINED;

    func = scm_c_eval_string("gnc:split->split-scm");
    if (!scm_is_procedure(func))
        return SCM_UNDEFINED;

    if (!split_type)
        split_type = SWIG_TypeQuery("_p_Split");

    arg = SWIG_NewPointerObj(split, split_type, 0);

    return scm_call_2(func, arg, SCM_BOOL(use_cut_semantics));
}
示例#30
0
static void
dirty_same_stylesheet(gpointer key, gpointer val, gpointer data)
{
    SCM dirty_ss = data;
    SCM rep_ss = NULL;
    SCM report = val;
    SCM func = NULL;

    func = scm_c_eval_string("gnc:report-stylesheet");
    if (scm_is_procedure(func))
        rep_ss = scm_call_1(func, report);
    else
        return;

    if (scm_is_true(scm_eq_p(rep_ss, dirty_ss)))
    {
        func = scm_c_eval_string("gnc:report-set-dirty?!");
        /* This makes _me_ feel dirty! */
        if (scm_is_procedure(func))
            scm_call_2(func, report, SCM_BOOL_T);
    }
}